迭代器协议
__next__和__iter__实现迭代器协议
什么是迭代器协议:对象必须提供一个next方法,执行该方法要哦返回迭代中的下一项,要么就引起一个stopiteration异常,来终止迭代
iter的功能就是把你的一个对象变成可迭代对象,所以类当中必须要有一个iter方法
class Foo:
def __init__(self,n):
self.n = n
def __iter__(self):
return self
def __next__(self):
if self.n ==12:
raise StopIteration('太多了,停止了')
self.n+=1
return self.n
f1 = Foo(10)
print(f1.__next__())
print(f1.__next__())
# f1 = Foo()
for i in f1: #iter(f1)===>f1.__iter__()
print(i)#之前也谈到过for循环会捕捉到Stopiteration异常然后终止掉
斐波那契数:后面那个数是前两个数之和,用迭代器协议实现斐波那契数:
class Fib:
def __init__(self):
self._a = 1
self._b = 1
def __iter__(self):
return self
def __next__(self):
if self._a>100:
raise StopIteration('stop')
self._a,self._b = self._b,self._a+self._b
return self._a
f1 = Fib()
print(next(f1))
print(next(f1))
print(next(f1))
for t in f1:
print('111111111111111')
print(t)
描述符:
描述符本质就是一个新式类,在这个新式类中,至少实现了__get__()
,__set__()
,__delete__()
中的一个,这也被称为描述符协议
class Foo:
def __get__(self, instance, owner):
print('get')
def __set__(self, instance, value):
print('set')
def __delete__(self, instance):
print('delete方法')
#描述符的作用是在代理另外一个属性的(必须把描述符定义成为这个类的类属性,不能定义到构造函数中)
class Bar:
x = Foo()
b1 = Bar()
b1.x#必须是其他类调用时才会触发
b1.x = 1#同理
del b1.x#同理
#数据描述符:至少实现了__get__()
和__set__()
#非数据描述符:没有__set__()
注意:
1、描述符本身应该定义成新式类,被代理的类也应该是新式类
2、必须把描述符定义成另外一个类的雷属性,不能赢一到构造函数中
2的意思就是:
class Qqq:
q = Foo()#这个没问题
def __init__(self):
self.y = Foo()
这个就不叫描述符,对Y的修改不会触发Foo
中__get__
与__set__
方法
3、要严格遵循以下优先级,由高到低分别为:
1.类属性
2.数据描述符
3.实例属性
4.非数据描述符
5.找不到的属性触发__getattr__()
class Foo:
def __get__(self, instance, owner):
print('get')
def __set__(self, instance, value):
print('set')
def __delete__(self, instance):
print('delete方法')
类属性的优先级最高,之前x对应着上一个类的描述符,那么现在就覆盖了,所以和描述符就没关系了
class Bar:
x= Foo()
Bar.x = 1
print(Bar.x)
所以调用出来就是1,不会触发描述符
实力属性>非数据描述符(没有set方法):
class Foo:
def __get__(self, instance, owner):
print('get')
class Bar:
x = Foo()
b1 = Bar()
b1.x = 1
print(b1.__dict__)
输出:{‘x’: 1},实力属性比非数据描述符优先级要高