前面的代碼中,我們只給類定義了實例變量,同一個類建立的不同實例的實例屬性可以不同。要實現(xiàn)相同類的實例共享屬性,可以給類定義類屬性和類方法。
1.類屬性
顧名思義,類屬性就是這個屬性是屬于類的,而不是屬于某一個類實例的。例如以下類定義:
class Foo:
bar = 7
類Foo中沒有定義構造方法,但定義了一個類屬性。類屬性是所有這個類實例的僅有屬性,看具體操作:
>>> class Foo:
bar= 7
>>> foo = Foo()
>>> foo2 = Foo()
>>> Foo.bar
7
>>> foo.bar
7
>>> foo2.bar
7
>>> Foo.bar = 0
>>> foo.bar
0
>>> foo2.bar
0
以上是再Python交互環(huán)境下運行的結果??煽吹剑xFoo類和實例化之后,不管是Foo.bar,還是查看其實例的bar的值都為7。當調用Foo.bar = 0之后,其實例的bar屬性也都改變成了0。
注意:如果執(zhí)行foo.bar = 3,則此時執(zhí)行的是為foo這個實例添加了一個實例變量bar并賦值為3,并沒有改變Foo的類屬性bar的值,F(xiàn)oo.bar和foo2.bar返回的是類屬性,其值依然是0。而再引用foo.bar則訪問的是foo這個實例的實例變量,所以結果為3。
>>> foo.bar =3
>>> foo2.bar
0
>>> foo.bar
3
>>> Foo.bar
0
>>> foo.bar
3
實際上,foo的實例變量bar和類屬性bar重名了,引用foo.bar時,優(yōu)先引用了實例變量。此時我們可以理解為foo的實例變量遮蓋了其類屬性。而我們一般避免使用foo.bar = 3的形式來改變類的實例,同時也不使用與類屬性同名的實例變量。
2.類方法
下面是一個簡單的類的代碼,定義了一個類方法。
class Foo:
bar = 3
@classmethod
defc_mthd(cls,v):
print(cls.a,v)
以下為實例化類后調用結果和直接用類名的調用結果:
>>> f = Foo()
>>> f.c_mthd(0)
3 0
>>> Foo.c_mthd(0)
3 0
類方法是被classmethod裝飾器裝飾的,其第一個參數(shù)必須是cls,用它來代表類自身。其它參數(shù)使用方法與一般方法相同。
注意:類方法中不能使用實例屬性,因為調用時可能還沒有實例化該類,否則會出錯。
3.靜態(tài)方法
靜態(tài)方法在定義時就使用staticmethod裝飾器,其參數(shù)既不用self,也不用cls。從定義形式來看,就像定義一個普通函數(shù)一樣,如果不希望他被封裝在類一起,完全可以在類的外部進行定義一個普通函數(shù),然后在類內的需要的地方直接使用。
class Foo:
bar=3
@staticmethod
defs_mthd(v):
print(Foo.bar,v)
以下是其調用方式:
>>> Foo.s_mthd(0)
3 0
>>> f = Foo()
>>> f.s_mthd(0)
3 0
注意:同類方法相同的是靜態(tài)方法中也不能使用實例變量,但可以通過類名來使用類屬性。但一般情況下,我們定義的靜態(tài)方法中不應訪問類及其實例的屬性的。