1. 程式人生 > >Python 2.7 類(二)(完結)

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))

詳細教程:Python 2.7 Tutorial