Python中的型別關係和繼承關係

2021-03-31 08:56:29 字數 2588 閱讀 6191

在python中一切都是物件,每個物件都有乙個唯一的不可變的id(通過id函式查詢)。把乙個名字和乙個id關聯起來,就可以通過這個名字檢索到這個物件。如果乙個物件a持有另乙個物件b的id,那麼檢索到a之後就可以檢索到b,我們就說存在乙個a到b的導航。這種導航關係使得python中所有物件之間形成了乙個複雜的網路結構。

python程式的執行包括:

1. 修改這個網路結構;

2. 執行有***的**物件(code object或者說bytecode,見python language reference 3.2)

(***是指影響python虛擬機器之外的裝置,這些**都是用c或者別的語言寫的,python寫的**只能完成第一步的功能。print語句除外。)

python物件之間有兩種導航關係:繼承關係和型別關係,是python中最基本的關係。型別關係說明乙個物件是通過哪個物件建立的;繼承關係說明物件之間的父子關係,這種父子關係在名字的解析過程中起到作用。這裡我首先說new style類之間的這兩種關係,掌握了new style類的關係後,再來說明classic類就容易了。

首先需要說明一下的是內建模組中的type是什麼。大家都知道type可以用來判斷乙個物件的型別,好像是乙個函式。實際上在2.2中type是乙個類,而且不是普通的類,是乙個可以建立類的類,稱為元類。你執行type(type)試一下,列印的是

。type類是python型別系統的核心。用type作為乙個判斷型別的函式使用是比較特殊的情況,或許是由歷史原因造成的,用typeof或許更合適。

如何構造乙個型別

你肯定知道是用class語句。但是實際上,在python核心看來,只有一種方式,那就是呼叫type的建構函式(因為type是乙個型別)。當執行:

class a(object): 

def f(self): print 1

python解析器就會執行如下**所示功能:

def f(self): print 1

a=type('a', (object,), ) # 引數為(名字, 父類tuple,成員dict)

del f

兩者效果幾乎是一樣的,你可以試一下。

型別關係的確定除了使用type之外,還可以使用__class__屬性。如:

class a(object): pass

a=a()         

a.__class__  # 'class __main__.a'

a.__class__  # 'type 

'

type.__class__ # 'type 

'

type.__class__.__class__ # 'type 

'

type.__class__ is type.__class.__class__ # true

繼承關係

繼承關係只發生在型別之間,繼承關係構成乙個有向圖。所有的型別都是從object繼承來的。「所有的」當然也包括type。object的父類還是object。object作為乙個型別物件也是有其型別的,這個型別就是type。所以object和type之間的關係就好比先有雞還是先有蛋的問題了:type是從object繼承的(繼承關係);object是由type生成的(型別關係)。通過issubclass或者__bases__屬性來判斷兩個類之間的繼承關係。

那麼從type繼承意味著什麼呢?那意味著這個類的型別是type,同時父類也是type。但是這種做法在一般的程式設計中是沒有什麼意義的(卻是meta programmming的核心)。因為一般都用class語句,而不是通過呼叫type的建構函式來建立型別物件。為了說明語法還是舉個例子:

class mytype(type): pass

a=mytype('a', (object,), {}) # 

del f

a.__class__ # class '__main__.mytype',元類為mytype

mytype.__class__ # 'type 

'

在用class定義乙個類時,會間接呼叫type的建構函式。但是通過設定__metaclass__屬性,可以不去呼叫type,而是呼叫type的子類。如:

class a(object):

__metaclass__ = mytype

a.__class__ # class '__main__.mytype' ,和上面的方式結果一樣。

由此,python物件的型別關係組成了乙個樹型結構,其中type處於樹的根部,由type或者type的子類構造的型別,包括class定義的類(間接呼叫type),呼叫type、type的子類建構函式建立的類,int list等系統定義型別處於中間節點,葉節點為instance物件。type本身的型別是什麼呢?還是type。這和根目錄的父目錄還是根目錄是一樣的。

classic類不同於new style類的地方就是當用class建立乙個類時,不是間接呼叫type,而是間接呼叫types.classtype,而types.classtype是由type建立的。

class a: pass

type(a) # type 'classobj'  ,注意沒有__class__屬性。

type(a) is types.classtype # true

types.classtype.__class__ # 'type'

Python中型別關係和繼承關係例項詳解

如果乙個物件a持有另乙個物件b的id,那麼檢索到a之後就可以檢索到b,我們就說存在乙個a到b的導航。這種導航關係使程式設計客棧得python中所有物件之間形成了乙個複雜的網路結構。python程式的執行包括 1.修改這個網路結構 2.執行有 的 物件 code object或者說bytecode,見...

Java泛型 繼承中型別變數的關係

通過例子來看泛型類在繼承中過程中型別變數應該具有怎樣的關係。首先給出幾個輔助類 package generic public class animal package generic public class person extends animal public string getname p...

python的多繼承關係

python和c 一樣,支援多繼承。概念雖然容易,但是困難的工作是如果子類呼叫乙個自身沒有定義的屬性,它是按照何種順序去到父類尋找呢,尤其是眾多父類中有多個都包含該同名屬性。class p1 object deffoo self print p1 foo class p2 object deffoo...