能夠在Python的類定義中直接添加靜態變量,以下例中的foo。此屬性屬於類C,能夠直接經過C.foo訪問,而無需實例化它。而實例屬性則只存在於對象的實例中,這也就意味着,每個不一樣的實例都有隻屬於本身的實例屬性。 python
class C: def __init__(self): pass foo = 'foo' c = C()
當咱們試圖經過一個實例訪問某個屬性的時候,解釋器會首先嚐試在實例的命名空間裏尋找,若是找不到就會去類屬性裏找。所以,便會出現下面的狀況: 函數
>>> C.foo 'foo' >>> c.foo 'foo' >>> C.foo = 'bar' >>> C.foo 'bar' >>> c.foo 'bar' >>> c.foo = 'instance' >>> c.foo 'instance' >>> C.foo 'bar'
當咱們實例化C類並將此實例賦值給c時,經過類C和實例c均可以訪問到foo屬性,實際上這時候訪問的是同一個「類屬性」(此屬性不存在於實例c的命名空間中)。這一點從下面,咱們經過類C改變foo的值後,經過實例c訪問foo的值也變了,能夠看得出來。而當咱們試圖經過實例c給foo賦值的時候,解釋器會把c.foo = 'instance' 這條命令理解爲「給實例c的foo屬性賦值」,而當他發現實例c沒有foo屬性的時候,便會自動的給實例c建立一個。這個時候再經過實例c去訪問類C的類屬性foo就是行不通的了。 ui
經過上面的例子能夠看到,類屬性的本體是屬於類自身的,而實例僅在沒有本身的同名實例屬性時才能夠訪問到他。這種特質的一個應用方式就是標記類自身的某些屬性,好比版本信息。 code
P.S.類定義的方法全都是類屬性,在實例被建立以前這些方法都不能被調用,由於他們尚未被綁定到特定的實例上。或者也能夠簡單的理解爲,缺乏能夠傳遞給類方法的self參數於是調用失敗。(arguments 0 given 1 required)除非:使用staticmethod()或classmethod()內建函數將類定義的某個方法「標記(tag),強制類型轉換(cast)或者轉換(convert)」爲靜態方法或者類方法。例如以下定義C類: orm
class C: def __init__(self): pass def foo(): print("calling static method foo().") foo = staticmethod(foo) def bar(cls): print("calling class method bar().") print("bar() is part of class:",cls.__name__) bar = classmethod(bar)
當調用foo()和bar()方法時,就不用再實例化C了。注意類方法bar()在定義時傳入的默認參數cls,它的做用與self相似(一樣只是一個約定俗成的名字cls用於指代類自己): 對象
>>> C.foo() calling static method foo(). >>> C.bar() calling class method bar(). bar() is part of class: C
關於Python的類定義方法時爲啥必須顯式傳遞一個self參數的問題,這用來表示該方法是不是綁定的,以及綁定在了何處(self / cls)。 ci