迭代器協議和描述符

迭代器協議

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章