2016-11-30 41 views
-1

我知道python的__getattr__是在訪問一個不存在的屬性時觸發的。Python:爲什麼訪問一個現有的屬性觸發「__getattr__」?

但在我的例子中,在c1的__init__裏面,我創建了一個名爲name的自我屬性。訪問時,兩種訪問方式都觸發__getattr__,因此打印出「無」。

這對我來說很奇怪。我想我的理解或我的代碼有一些問題?

$ cat n.py 

class c1(object): 
    def __init__(s): 
     print 'init c1' 
     s.name='abc' 
    def __getattr__(s,name): 
     print "__getattr__:"+name 
     return None 
    def __setattr__(s,name,value): 
     print "__setattr__:"+value 
    def __get__(s,inst,owner): 
     print "__get__" 

class d: 
    def __init__(s): 
     s.c=c1() 

c=c1() 
print c.name 
o=d() 
print o.c.name 

$ python n.py 

init c1 
__setattr__:abc 
__getattr__:name 
None 
init c1 
__setattr__:abc 
__getattr__:name 
None 

你可以看到,我定義s.name='abc'__init__,但訪問時,它無法識別。

+1

您的'__setattr__'方法不會執行任何操作,這就是爲什麼'name'屬性沒有設置的原因。 – vaultah

回答

4

實施__setattr__,並且它是試圖設置屬性時總是調用。您的版本只打印屬性:

def __setattr__(s,name,value): 
    print "__setattr__:"+value 

,沒有別的,這意味着該屬性是不實際設置。上述要求爲s.name='abc'表達式,name屬性從未設置,因此任何對name屬性的未來訪問都將再次發送到__getattr__

__setattr____dict__直接設定值:

def __setattr__(self, name, value): 
    print "__setattr__:" + value 
    self.__dict__[name] = value 

或讓你的類new-style class(從object繼承),並且可以重複使用基實現與super(c1, self).__setattr__(name, value)

作爲一個方面說明:您實施了c1.__get__,想必是爲了讓課程成爲descriptor object。但是,描述符協議只適用於類屬性,而不是實例屬性,然後僅適用於新樣式類。您的類d不是新式類,並且您使用實例屬性c來存儲c1實例。

相關問題