python中的類叫class object,類的實例叫instance object.
類 Class Objects
類擁有兩種操作,1.類屬性 attribute references 2.實例化instantiation
類屬性就相當於專屬於一個類的變量(即某些語言中的類的靜態公共變量static public),使用方法是:類名稱.類屬性名稱 實例化則是創建一個類的實例的方法,使用方法是:類名稱()
在使用實例化方法后,將會創建一個空的類實例,一般的python類的定義中會有一個特殊的方法來初始化,這個方法就是__init__(),當調用了類的實例化方法后,__init__()方法會立刻被這個類的實例調用.也就是說,__init__()不是構造函數,而是一個普通的方法. 類的實例 Instance Objects
類的實例只擁有一種操作,這就是 1.屬性調用 attribute references.
屬性調用指 1.數據屬性 2.方法
數據屬性不需要預先定義!當數據屬性初次被使用時,它即被創建並賦值(they spring into existence when they are first assigned to) 看下面的例子
class Test: pass t=Test() t.name='notus' print t.name
我們在類Test中並沒有定義name這個數據屬性,但是在代碼中卻可以直接使用,這就是數據屬性. 現在,拋開廣義上對屬性attribute的解釋,在實際編程中經常用的屬性這個詞,在python的class中有兩種屬性:類屬性,數據屬性.(大多數編程語言都有這樣兩種屬性).類屬性屬於類,數據屬性屬於類的實例.我們假設有類Test,則一般這兩種屬性的用法是
Test.mode t=Test() t.name
那么這兩種屬性應該在什么時候定義呢?
按照上面的討論可知,數據屬性不需要預先定義,當數據屬性初次被使用時,它即被創建並賦值.而實際上,類屬性也是如此.
因此,我們有了下面的例子
class Test: pass t=Test() t.name='notus' print t.name Test.mode='auto' print Test.mode
大家看,數據屬性name和類屬性mode均沒有在類中被定義,你要做的,只是在需要的時候使用他們即可.如何預先給屬性賦值
可以在類的定義中使用屬性,先看這個例子
class Test: def ask(theInstance): theInstance.name='notus' Test.mode='auto' ##print Test.mode t=Test() ##print t.name t.ask() print Test.mode print t.name
類Test有方法ask.注意看程序中被注釋掉的兩行,在沒有使用ask()方法前,運行被注釋的那兩句的任一句均會出錯,提示"class Test has no attribute ...".但運行ask()后,我們在ask()方法中初始了這兩個屬性 ,則運行通過.
注意看ask()接收的參數theInstance,這個傳過來的就是程序中類Test的實例t .一般的命名規范建議將這個參數命名為self.這個參數是python自動傳入的,所以不需要再在程序中傳.
如果想要在類實例化后立刻使用這些屬性,那就應該把這些屬性的初始放在__init__()方法中,前面說過了,__init__()方法在類的實例化結束后立刻被自動調用. 所以我們的例子程序可以改成這樣
class Test: def __init__(self): self.name='notus' Test.mode='auto' ##print Test.mode t=Test() ##print t.name print Test.mode print t.name
所以可以有這樣的類定義
class Test: def __init__(self): self.name='notus' Test.mode='auto' def ask(self): self.date='2008' ##print Test.mode t=Test() ##print t.name print Test.mode print t.name ##print t.date t.ask() print t.date
數據屬性date只有在調用了ask()方法后才可以被使用.當然這樣也可以使用這個屬性
##print Test.mode t=Test() ##print t.name print Test.mode print t.name t.date='2007' print t.date
在程序中創建了date這個數據屬性.可以想象,之后調用ask()方法時,數據屬性date已經存在,只是被改變了值. 不用方法也可以初始化屬性
看下面的示例程序
class Test: action='win the game' #類屬性 print Test.action t=Test() print t.action Test.action='at least 1 point' print Test.action print t.action t.action='dont lose' print Test.action print t.action
運行的結果如下
win the game
win the game
at least 1 point
at least 1 point
at least 1 point
dont lose
現象可以概括為:"改變類屬性,數據屬性跟着變,改變數據屬性,類屬性不變".
class AAA(): aaa = 10 #類屬性 情形1 obj1 = AAA() obj2 = AAA() print obj1.aaa, obj2.aaa, AAA.aaa 情形2 obj1.aaa += 2 print obj1.aaa, obj2.aaa, AAA.aaa 情形3 AAA.aaa += 3 print obj1.aaa, obj2.aaa, AAA.aaa
引用
對於情形1,我相信絕大多數人都會正確的說出結果,那就是:
10 10 10
對於上面這個結果,沒有任何懸念,通過兩個AAA的實例,以及通過AAA類名引用aaa屬性值,都是同樣的答案。 那在情形2中,應該是什么結果呢,我相信大多數人還是會說出正確的結果:
12 10 10
在上面這個結果中,一旦執行了obj1.aaa += 2,也就意味着obj1這個實例有了個實例的屬性值,他的屬性名稱也為aaa,那是不是obj1的aaa是個新的屬性呢,實際上可以說法是對,但也不對,實際上obj1.aaa += 2這個代碼的執行,並不像我們想象的那么簡單,首先他會到obj1所屬的類AAA的屬性列表中去找一個名稱為aaa的屬性,如果有,他就會返回該值作為 obj1中aaa的初始值,也就是說,這以后obj1.aaa的這個屬性值跟AAA.aaa就基本沒有關系了。 那在情形3中呢,答案是什么呢:
12 13 13
這又怎么說呢,其實很簡單,AAA.aaa對AAA類屬性做了一次設置,obj1.aaa經過一次+=操作后,實際上與AAA.aaa脫離了關系,而obj2.aaa沒有經過任何的屬性操作,因此其只會從其所屬的類AAA中去獲得aaa,並返回。
引用
《python核心編程》
如果嘗試在實例中設定或更新類屬性會創建一個實例屬性 c.version,后者會阻止對類屬性
C.versioin 的訪問,因為第一個訪問的就是 c.version,這樣可以對實例有效地“遮蔽”類屬性C.version,直到 c.version 被清除掉。
