Python
學習筆記(四)
Python
在盡可能不增加新的語法和語義的情況下加入了類機制。這種機制是
C++
和
Modula-3
的混合。
Python
中的類沒有在用戶和定義之間建立一個絕對的屏障,而是依賴于用戶自覺的不去
“
破壞定義
”
。然而,類機制最重要的功能都完整的保留下來。類繼承機制允許多繼承,派生類可以覆蓋(
override
)基類中的任何方法,方法中可以調用基類中的同名方法。對象可以包含任意數量的私有成員。
在
Python
中
“
對象
”
這個詞不一定指類實例。
Python
中并非所有的類型都是類:例如整型、鏈表這些內置數據類型就不是,甚至某些像文件這樣的外部類型也不是,這一點類似于
C++
和
Modula-3
,而不像
Smalltalk
。然而,所有的
Python
類型在語義上都有一點相同之處:描述它們的最貼切詞語是
“
對象
”
。
對象是被特化的,多個名字(在多個作用域中)可以綁定同一個對象。這相當于其它語言中的別名。通常對
Python
的第一印象中會忽略這一點,使用那些不可變的基本類型(數值、字符串、元組)時也可以很放心的忽視它。然而,在
Python
代碼調用字典、鏈表之類可變對象,以及大多數涉及程序外部實體(文件、窗體等等)的類型時,這一語義就會有影響。這通用有助于優化程序,因為別名的行為在某些方面類似于指針。例如,很容易傳遞一個對象,因為在行為上只是傳遞了一個指針。如果函數修改了一個通過參數傳遞的對象,調用者可以接收到變化--在
Pascal
中這需要兩個不同的參數傳遞機制。
下面程序說話:
class MyClass:
??? "A simple example class"
??? i = 12345
??? def f(self):
??????? return 'hello world'
那么
MyClass.i
和
MyClass.f
是有效的屬性引用,分別返回一個整數和一個方法對象。也可以對類屬性賦值,你可以通過給
MyClass.i
賦值來修改它。
__doc__
也是一個有效的屬性,返回類的文檔字符串:
"A simple example class"
。
不過多數情況加上
__init__
函數。類似構造函數。第一個參數一般
self
,為其自身。
派生類可能會覆蓋其基類的方法。因為方法調用同一個對象中的其它方法時沒有特權,基類的方法調用同一個基類的方法時,可能實際上最終調用了派生類中的覆蓋方法。(對于
C++
程序員來說,
Python
中的所有方法本質上都是虛方法。)
派生類中的覆蓋方法可能是想要擴充而不是簡單的替代基類中的重名方法。有一個簡單的方法可以直接調用基類方法,只要調用:
"BaseClassName.methodname(self, arguments)"
。有時這對于客戶也很有用。(要注意的中只有基類在同一全局作用域定義或導入時才能這樣用。)
Python
同樣有限的支持多繼承形式。多繼承的類定義形如下例:
class DerivedClassName(Base1, Base2, Base3):
??? <statement-1>
??? .
??? .
??? .
??? <statement-N>
這里唯一需要解釋的語義是解析類屬性的規則。順序是深度優先,從左到右。因此,如果在
DerivedClassName
(示例中的派生類)中沒有找到某個屬性,就會搜索
Base1
,然后(遞歸的)搜索其基類,如果最終沒有找到,就搜索
Base2
,以此類推。
小漏洞:派生類和基類取相同的名字就可以使用基類的私有變量。