34.1-slots、反向方法、生成器交互

2020-01-06  本文已影响0人  BeautifulSoulpy

倘若才华得不到承认,与其苦恼,不如坚持,在坚持中积蓄力量,终有一天,你会发光!

总结:

  1. 算法和内存问题,仅存在理论中(面试中会问道),实际应用生产中不会在意这些问题;内存不够就买;

1. _slots_

问题的引出:都是字典惹的祸。
字典为了提升查询效率,必须用空间换时间。
一般来说一个对象,属性多一点,都存储在字典中便于查询,问题不大。
但是如果数百万个对象,那么字典占得就有点大了。
这个时候,能不能把属性字典 dict 省了? Python提供了 _slots_

  1. _slots_ = 'y z a'.split() # 固定实例属性
  2. 没有dict, 只要定义了_slots_;
  3. _slots_不会继承,只会影响当前类;
#__slots__ = 'y z a'.split() # 实例允许的属性;
class A:
    X = 1
    
    __slots__ = ['y','z','a']  # 实例允许的属性
    #__slots__ = 'y z a'.split() # 实例允许的属性
    def __init__(self):
        self.y = 5
        self.z = 6      
    
    def show(self):
        print(self.X,self.y,self.z)
a = A()
#print(a.__dict__)   # 没有dict, 只要定义了__slots__;
print(a.X)
print(a.y)
print(a.z)
a.a = 200
print(a.a)
#------------------------------------------------------------------------------
1
5
6
200

_slots_ 告诉解释器,实例的属性都叫什么,一般来说,既然要节约内存,最好还是使用元组比较好。
一旦类提供了 _slots_ ,就阻止实例产生 _dict_ 来保存实例的属性。

应用场景
使用需要构建在数百万以上对象,且内存容量较为紧张,实例的属性简单、固定且不用动态增加的场景

2. 未实现和未实现异常

print(type(NotImplemented))
print(type(NotImplementedError))
# <class 'NotImplementedType'>
# <class 'type'>
# raise NotImplemented
raise NotImplementedError

NotImplemented是个值,单值,是NotImplementedType的实例
NotImplementedError 是类型,是异常,返回type;

3. 运算符重载中的反向方法

前面学习过运算符重载的方法,例如_add和_iadd

class A:
    def __init__(self,x):
        self.x = x
        
    def __add__(self,other):
        print('1 add~~~~~~~~~~~~~~~~~~~')
        return self.x+other.x
    
    def __iadd__(self,other):
        print('2 iadd~~~~~~~~~~~~~~~~~~')
        return type(self)(self.x+other.x)
    
    def __radd__(self,other):
        print('3 radd~~~~~~~~~~~~~~~~~')
        return self.x + other.x
    
a = A(4)
b = A(5)
c = A(6)
print(a,b,c)
print(b + a)
#---------------------------------------------------------------------------------
<__main__.A object at 0x0000024FD4948E10> <__main__.A object at 0x0000024FD4948DA0> <__main__.A object at 0x0000024FD4955588>
1 add~~~~~~~~~~~~~~~~~~~
9

4. 生成器交互

无限计数器的制作;

def getid():
    start = 0
    while True:
        start += 1
        yield start
        
g = getid()
for _ in range(5):
    print(next(g))
#----------------------------------------------
1
2
3
4
5


生成器提供了一个send方法,该方法可以和生成器方向沟通。
调用send方法,就可以把send的实参传给yield语句做结果,这个结果可以在等式右边被赋值给其它变量。
send和next一样可以推动生成器启动并执行;

def getid(start=0):
    start = start
    base = None
    while True:
        if base is None:
            start += 1
        else:
            start = base + 1
        base = yield start
        #print(base)
g = getid()
for _ in range(5):
    print(next(g))
g.send(100)
for _ in range(5):
    print(next(g))
#------------------------------------
1
2
3
4
5
102
103
104
105
106

上一篇 下一篇

猜你喜欢

热点阅读