迭代器協議
__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},實力屬性比非數據描述符優先級要高