Python 2.7 類(二)(完結)
5 繼承
繼承語法
# 定義類
class C:
pass
# 繼承類
class CC(C):
pass
# 繼承模組類
class CCC(inheritance.MC):
pass
在解析屬性引用時,如果請求屬性沒有在類中被找到,將會在基類中繼續搜尋。如果基類從其它類中派生而來,此過程會被遞迴應用。
派生類會重寫基類方法。由於在呼叫相同物件中的其他方法時,方法沒有特別的許可權,所以一個基類的方法在呼叫定義在相同基類中的其他方法時,可能會呼叫到重寫此方法的派生類中的方法。
派生類重寫基類方法
# 定義基類 class MC: def fff(self): print "This is MC" # 定義派生類(擴充套件基類方法) class CC(MC): def fff(self): MC.fff(self) print "This is Cc"
判斷繼承內建函式
# 判斷例項是否由指定類派生而來
print isinstance(x, int)
# 判斷類是否由指定類派生而來
print issubclass(CC, MC)
5.1 多重繼承
Python支援有限形式的多重繼承。
import base class A: def aa(self): print "This is A" class B: def bb(self): print "This is B" class C(A, B, base.Base): def cc(self): print "This is C"
與只繼承一個類相比,唯一的規則是深度優先,由左到右。
方法解析順序可以動態改變以支援對super()的協同呼叫。
由於所有多重繼承的情況都表現出菱形關係,所以動態順序順序必要的。(至少一個雙親類可以通過由底層類出發的多條路徑訪問。)
為了防止基類被訪問超過一次,動態演算法線性化搜尋順序,以一種保持每個類指定的從左到右順序,只調用每個雙親一次,並且不變(即類可以在不影響其雙親優先度的情況下子類化)的方法達成。
6 私有變數與類區域性引用
Python中不存在“私有”例項變數。
Python中有一個通用約定:以下劃線為字首的名稱應該被看作是API的非公開部分。
由於存在類私有成員的有效用例(即避免名稱與子類中定義的名稱衝突),存在對命名修改機制的有限支援。
任何形式為__spam(開頭至少兩個下劃線,結尾最多一個下劃線)的識別符號會被文字替換為_classname__spam,其中classname是當前類名。只要出現在類定義中,就可以在不考慮識別符號句法位置的情況下,完成修改。
命名修改有助於子類重寫方法時不會破壞內部類方法呼叫。
注意,傳遞給exec()、eval()或execfile()的程式碼不會將呼叫者的類視為當前類,這一點類似global語句的效果。
7 碎片補充
# 使用類繫結一組資料名稱
class C:
pass:
c = C()
c.n = 'Jo'
c.j = 123
需要特殊抽象資料型別的一段Python程式碼可以被傳入一個模仿資料型別方法的類。
例項方法物件也具有屬性。
# 定義類
class CC:
def ff(self):
print "fff"
# 例項化
x = CC()
# 獲取例項物件
x.ff.im_self
# 獲取方法對應的函式物件
x.ff.im_func
8 異常也是類
使用者定義的異常由類標識。使用此機制可以建立異常的擴充套件架構。
# raise語句
class B:
pass
class C(B):
pass
class D(C):
pass
for c in [B, C, D]:
try:
raise c()
except D:
print "D"
except C:
print "C"
except B:
print "B"
如果異常與except子句中的類相同或是它是異常的基類,異常與except子句中類相容。
如果一個未處理異常的錯誤資訊沒有被列印,異常的類名將會被列印,然後是冒號與空格,最後是使用內建函式str()轉化為字串的例項。
9 迭代器
迭代過程中,for語句呼叫容器物件的iter()。此函式返回一個迭代器物件,此物件定義了一次訪問容器中一個元素的方法next()。當沒有元素時,next()提出了StopIteration異常,此異常告知for迴圈終止。
在類中新增迭代行為,需要定義__iter__()方法,返回一個具有next()方法的物件,也可以在類中同時定義next(),然後令__iter__()返回self。
class Reverse:
def __init__(self, data):
self.data = data
self.index = len(data)
def __iter__(self):
return self
def next(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
10 生成器
生成器是建立迭代器的簡單有效的工具。它們想常規函式一樣使用,但是使用yield語句返回資料。每次呼叫next(),生成器都會從中斷處繼續(它會記住所有的資料值與最後執行的語句)。
def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
for char in reverse('sdgaf'):
print char
生成器會自動建立__iter__()與next()方法。
區域性變數與執行狀態會在呼叫之間自動儲存。這就省略了self.index與self.data的使用,程式碼更整潔。
當生成器終止時,它會自動提出一個StopIteration。
11 生成器表示式
一些簡單的生成器可以使用類似列表推導的語法編碼為表示式,不過使用括號代替方括號。這些表示式被設計為用於生成器通過封閉函式立即使用的情況。生成器表示式比完整的生成器定義更緊湊但功能較少,與等價的列表推導式相比,更具記憶體友好性。
sum(i * i for i in range(10))