2017-09-20 17 views
1

假設我們定義以下蟒蛇描述python解釋器如何決定何時調用__set__和__get__方法,何時不調用?

class FooDescriptor(): 
    def __init__(self, name='foo', initval='initval'): 
     self.name = name 
     self.val = initval 

    def __get__(self, instance, cls): 
     print("invoke get {} in instance {} in class {}".format(self.name, instance, cls)) 
     return self.val 

    def __set__(self, instance, val): 
     print("invoke set {} in instance {}".format(self.name, instance)) 
     self.val = val 

現在,如果我們定義的類FooFooDescriptor類型的類屬性和相同類型的實例屬性:

class Foo(): 
    cdescr = FooDescriptor(name='class attribute descr', initval=1) 
    def __init__(self): 
     self.idescr = FooDescriptor(name='instance attribute descr', initval=2) 

我們得到的期望的類別描述符的行爲:

>>> foo = Foo() 
>>> foo.cdescr 
invoke get class attribute descr in instance <__main__.Foo object at 0x10189ecc0> in class <class '__main__.Foo'> 
1 
>>> foo.cdescr = 100 
invoke set class attribute descr in instance <__main__.Foo object at 0x10189ecc0> 
>>> foo.cdescr 
invoke get class attribute descr in instance <__main__.Foo object at 0x10189ecc0> in class <class '__main__.Foo'> 
100 

然而,對於th Ë實例屬性idescr,不要當屬性被訪問或設置調用描述對象的__set____get__方法:

>>> foo.idescr 
<__main__.FooDescriptor object at 0x10189ecf8> 
>>> foo.idescr = 120 
>>> foo.idescr 
120 
>>> type(foo.idescr) 
<class 'int'> 

任何答案爲了更好地理解描述符的範圍和蟒蛇如何決定調用他們的__set____get__當看到屬性protocal .將不勝感激。

+0

描述符協議不適用於實例屬性。描述符是成爲* class *對象的成員,而不是實例對象 –

回答

1

這是因爲在查找實例類的屬性時使用了描述符。如果它是一個實例屬性,它不會打擾描述符協議。

一個很好的ressource對於這種問題是約內爾的元類的博客,其中包含該圖像也顯示了當使用描述:

enter image description here

(圖片來自here複製)

因爲cdescrclass.__dict__中,並且具有__get____set__它將返回描述符__get__返回的內容。但由於idescr不在class.__dict__中,因此它只會返回存儲在instance.__dict__中的內容。

相關問題