2010-08-03 54 views
0

請參閱下面的示例。對類實例'object'使用__class__前綴給出了預期的結果。爲什麼類變量在類實例'c()'中沒有__class__前綴,甚至可用?在什麼情況下使用?爲什麼在沒有__class__前綴的情況下可以訪問類變量?

>>> class c: 
     x=0 


>>> c.x 
0 
>>> c().x 
0 
>>> c().__class__.x 
0 
>>> c.x += 1 
>>> c.x 
1 
>>> c().x += 1 
>>> c.x 
1 
>>> c().__class__.x += 1 
>>> c.x 
2 
>>> 

回答

2

爲什麼是類變量,甚至 可在類實例 'C()' 沒有前綴?

你可以將它有用地認爲是「繼承自」他們的類的實例。 IOW,當在實例x(例如x.atr)上查找名爲'atr'的屬性時,除非在實例本身中發現它,否則它將在該類中查找(這反過來可能導致在類的基礎中查找,在mro鏈中查找) 。

在什麼情況下使用?

最常見的一個案例:

class sic(object): 
    def foo(self): ... 

x = sic() 
x.foo() 

你可能不會想到的foo爲「類變量」,但這是因爲「變量」實在是毫無意義的在Python,這相當與交易名稱屬性。在給定的詞法範圍內沒有用於可調用對象和不可調用對象的獨立名稱空間:它們都共享相同的名稱空間。

因此,舉例來說,如果你沒有x.foo = 23,那麼你可以不叫x.foo()更多 - 因爲x.foo查找會給你的價值23,這是一個int,而不是調用。

另一種方式來看待這個是

class one(object): 
    foo = lambda self: ... 

class two(object): 
    def foo(self): ... 

class three(object): 
    foo = 23 

目前沒有深厚的區別 - 他們一路來設置類屬性foo(其中一個是不可調用的,有兩個;一個與def約束聲明,其中兩項與作業有關;在這些類的實例的屬性查找方面,存在差別而不是)。

的不可贖回屬性的典型用途是:

class zap(zop): 
    zep = None 

    def blub(self): 
    if self.zep is None: self.zep = 23 
    ...&c... 

沒有必要給zap一個__init__self.zep = None,並組團到超類的__init__(如果有的話) - 簡單到只是繼承zop「 (如果有的話)並儘可能使用class屬性(當且僅當在該實例上調用blub時,它纔會變成實例屬性) - 對於blub永遠不會存在的實例,也可以節省一點內存所謂;-)。

+0

感謝您的詳細回覆。你能解釋一下PL在這個例子中的差異,爲什麼是類變量,實例變量同樣在這種情況下: >>> C類: \t X = [1] \t >>> CX [1] >>> C()x.append(2) >>> CX [1,2] >>> 編輯:該代碼不顯示格式化的,但這個想法是使用一個列表,而不是整數的 – user284094 2010-08-03 03:30:32

+0

@ tx10:最好爲此提出一個新問題。如您所見,無論是問題還是答案,都很難在評論中正確顯示代碼。 – 2010-08-03 04:30:58

+0

@ tx10,與@Mark達成100%的協議。無論如何,綁定一個裸號(例如通過賦值或者「def」)並且調用一個變異方法(例如你的例子中的append)完全,完全,完全和本質上是不同的,獨特的,獨立的和不相交的問題,很難看出爲什麼有人會希望他們有相同的行爲(儘管顯然很多Python初學者都這麼做)。 – 2010-08-03 04:37:20

相關問題