class語句
Class語句表面上看起來和其它OOP語言的工具類似。像def語句一樣,class語句也是創建了一個類對象,並把該對象賦值給類名。在沒有執行class語句之前,你的類都是不存在的。
class語句的一般形式:
class語句是複合語句,其縮進語句的主體一般都是出現在頭一行下邊。
class <name>(superclass,...):
data = value #類變量,被所有實例共享
def method(self,...):
self.member = value
在class頂層內賦值的變量名都成爲類的變量,這個變量被所以該類的實例所共享(共享相同的一個內存)。
- 就像函數一樣,class語句是本地作用域,由內嵌的賦值語句建立的變量名,就存在於這個本地作用域內。
- 就像模塊內的變量名,在class語句內賦值的變量名會變成類對象中的屬性。如果在類的實例中進行屬性賦值,就會在實例中創建一個變量,這個變量就由實例所特有。
>>> class testdata:
... test=222
...
>>> a=testdata()
>>> b=testdata()
>>> c=testdata()
>>> a.test,b.test,c.test,testdata.test #都是使用的類變量
(222, 222, 222, 222)
>>> a.test=333 #實例中變量賦值
>>> a.test,b.test,c.test,testdata.test #改變的實例對象中的變量,類變量沒有改變
(333, 222, 222, 222)
>>> testdata.test=444 #修改類變量
>>> a.test,b.test,c.test,testdata.test
(333, 444, 444, 444) #共享類變量的實例中,變量都發生了改變
>>>
方法
類中的定義的函數就稱爲方法,語法與函數很類似,唯一不同的就是方法的第一個參數總是會接受方法的調用對應的類的實例對象,按照慣例,第一個參數通常稱爲self(其實名字不重要,重要的是位置。)這個參數實現了一個鉤子,從而返回調用類方法的實例對象。在子類中,也可以調用父類中的方法。
繼承
之前講過,在使用點運算時(object.attribute)Python內部實際上是去按照一定的規則去查找屬性樹,以取出對應的值。那麼通常來說,各個命名空間的屬性有如下規則:
- 實例的屬性一般是又對類內的self屬性(類創建的實例對象)進行運算而產生的
- 類屬性是在定義類時,直接在類內通過賦值運算產生的。
- 超類的鏈接是在類的定義時,在首行內的括號中給出。
抽象類
與其他OOP編程一樣,也可以在Python中實現抽象類,抽象類是會調用方法的類,但沒有繼承或定義該方法,而是期待該方法由子類填補。即**類的實現又子類來定義,而不是在超類中定義。**Python實現這種效果的方式很簡單:
>>> class superclass:
... def test(self):
... assert False,'action must be defined' #或者定義爲raise NotImplementedError('action must be defined')
...
>>> x=superclass()
>>> x.test() #不能由父類直接調用,而是由子類繼承定義後調用。
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in test
AssertionError: action must be defined
>>>
在Python3.0中,抽象類還可以使用關鍵字參數和特殊的語法裝飾器來定義一個抽象類:
>>> from abc import ABCMeta,abstractmethod
>>> class Super(metaclass=ABCMeta): #關鍵字參數來聲明這個是抽象類
... def delegate(self):
... self.action()
... @abstractmethod #聲明是抽象方法
... def action(self):
... pass
...
>>> x=Super()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Super with abstract methods action
>>> class sub(Super):
... pass
...
>>> x=sub()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class sub with abstract methods action
>>> class Sub(Super): #必須在子類中實現抽象方法後才能正常調用。
... def action(self):
... print('OK')
...
>>> x=Sub()
>>> x.delegate()
OK
>>> x.action()
OK
>>>