python元類的使用 python使用元類

2021-10-11 12:51:35 字數 2678 閱讀 9550

原文:

type()

動態語言和靜態語言最大的不同,就是函式和類的定義,不是編譯時定義的,而是執行時動態建立的。

比方說我們要定義乙個hello的class,就寫乙個hello.py模組:

當python直譯器載入hello模組時,就會依次執行該模組的所有語句,執行結果就是動態建立出乙個hello的class物件,測試如下:

>>> from hello importhello>>> h =hello()>>>h.hello()

hello, world.>>> print(type(hello))

>>> print(type(h))

type()函式可以檢視乙個型別或變數的型別,hello是乙個class,它的型別就是type,而h是乙個例項,它的型別就是class hello。

我們說class的定義是執行時動態建立的,而建立class的方法就是使用type()函式。

type()函式既可以返回乙個物件的型別,又可以建立出新的型別,比如,我們可以通過type()函式建立出hello類,而無需通過class hello(object)...的定義:

>>> def fn(self, name='world'): #先定義函式

...print('hello, %s.' %name)

...>>> hello = type('hello', (object,), dict(hello=fn)) #建立hello class

>>> h =hello()>>>h.hello()

hello, world.>>> print(type(hello))

>>> print(type(h))

要建立乙個class物件,type()函式依次傳入3個引數:

class的名稱;

繼承的父類集合,注意python支援多重繼承,如果只有乙個父類,別忘了tuple的單元素寫法;

class的方法名稱與函式繫結,這裡我們把函式fn繫結到方法名hello上。

通過type()函式建立的類和直接寫class是完全一樣的,因為python直譯器遇到class定義時,僅僅是掃瞄一下class定義的語法,然後呼叫type()函式建立出class。

正常情況下,我們都用class ***...來定義類,但是,type()函式也允許我們動態建立出類來,也就是說,動態語言本身支援執行期動態建立類,這和靜態語言有非常大的不同,要在靜態語言執行期建立類,必須構造源**字串再呼叫編譯器,或者借助一些工具生成位元組碼實現,本質上都是動態編譯,會非常複雜。

metaclass

除了使用type()動態建立類以外,要控制類的建立行為,還可以使用metaclass。

metaclass,直譯為元類,簡單的解釋就是:

當我們定義了類以後,就可以根據這個類建立出例項,所以:先定義類,然後建立例項。

但是如果我們想建立出類呢?那就必須根據metaclass建立出類,所以:先定義metaclass,然後建立類。

連線起來就是:先定義metaclass,就可以建立類,最後建立例項。

所以,metaclass允許你建立類或者修改類。換句話說,你可以把類看成是metaclass建立出來的「例項」。

metaclass是python物件導向裡最難理解,也是最難使用的魔術**。正常情況下,你不會碰到需要使用metaclass的情況,所以,以下內容看不懂也沒關係,因為基本上你不會用到。

我們先看乙個簡單的例子,這個metaclass可以給我們自定義的mylist增加乙個add方法:

定義listmetaclass,按照預設習慣,metaclass的類名總是以metaclass結尾,以便清楚地表示這是乙個metaclass:

#metaclass是類的模板,所以必須從`type`型別派生:

classlistmetaclass(type):def __new__(cls, name, bases, attrs):

有了listmetaclass,我們在定義類的時候還要指示使用listmetaclass來定製類,傳入關鍵字引數metaclass:

class mylist(list, metaclass=listmetaclass):pass

當我們傳入關鍵字引數metaclass時,魔術就生效了,它指示python直譯器在建立mylist時,要通過listmetaclass.__new__()來建立,在此,我們可以修改類的定義,比如,加上新的方法,然後,返回修改後的定義。

__new__()方法接收到的引數依次是:

當前準備建立的類的物件;

類的名字;

類繼承的父類集合;

類的方法集合

測試一下mylist是否可以呼叫add()方法:

>>> l =mylist()>>> l.add(1)>>l

[1]而普通的list沒有add()方法:

>>> l2 =list()>>> l2.add(1)

traceback (most recent call last):

file"", line 1, in attributeerror:'list' object has no attribute 'add'

動態修改有什麼意義?直接在mylist定義中寫上add()方法不是更簡單嗎?正常情況下,確實應該直接寫,通過metaclass修改純屬**。

但是,總會遇到需要通過metaclass修改類定義的。orm就是乙個典型的例子。

要編寫乙個orm框架,所有的類都只能動態定義,因為只有使用者才能根據表的結構定義出對應的類來

python元類的使用 Python的元類如何使用

這次給大家帶來python的元類如何使用,使用python元類的注意事項有哪些,下面就是實戰案例,一起來看一下。今天我的任務就是徹底明白什麼是元類,一起看看。要搞懂元類,我們還是先從物件說起。python 一切皆物件,這句話你一定有聽說過 現在你就聽說了 乙個數字是物件,乙個字串是物件,乙個列表是物...

python元類的使用 Python 元類使用講解

我要一大群的類都具有一種特點,我怎麼給他們加上呢?模板嘛,我從這個模板建立一群類不就ok了?那就需要元類了。定義乙個元類 就是乙個類的模板!莫多想,還要記住這是類級別的,不是物件級別的!如下 class mymeta type def init cls,name,bases,dic print cl...

python如何使用元 Python的元類如何使用

這次給大家帶來python的元類如何使用,使用python元類的注意事項有哪些,下面就是實戰案例,一起來看一下。今天我的任務就是徹底明白什麼是元類,一起看看。要搞懂元類,我們還是先從物件說起。物件 object python 一切皆物件,這句話你一定有聽說過 現在你就聽說了 乙個數字是物件,乙個字串...