1. 程式人生 > >理解python中的元類(metaclass)

理解python中的元類(metaclass)

本文是根據stackoverflow上關於“What are metaclasses in Python?”的回答翻譯總結而成的。原資料連線:https://stackoverflow.com/questions/100003/what-are-metaclasses-in-python

1. 類物件(class as object)

在瞭解元類(metaclass)之前, 首先得熟悉一下python中的類(class)。python對於什麼是類有一個很獨特的定義,借鑑與Smalltalk程式語言。在很多程式語言中,類僅僅是一段用來描述如何產生物件的程式碼。python中的類也有這種功能。>>> class ObjectCreator(object):    ... pass...>>> my_object = ObjectCreator
()>>> print(my_object)<__main__.ObjectCreator object at 0x8974f2c>但是,在python中,類的作用遠不止這個。類本身也是物件。因為類是物件,所以我們可以對其進行很多操作:
  • 賦值給一個變數
  • 複製類
  • 新增屬性
  • 作為引數傳遞給函式
>>> class ObjectCreator(object):...     pass...>>> print(ObjectCreator) # you can print a class because it's an object<class
'__main__.ObjectCreator'>>>> def echo(o):... print(o)...>>> echo(ObjectCreator) # you can pass a class as a parameter<class '__main__.ObjectCreator'>>>> print(hasattr(ObjectCreator, 'new_attribute'))False>>> ObjectCreator.new_attribute = 'foo' # you can add attributes to a class
>>> print(hasattr(ObjectCreator, 'new_attribute'))True>>> print(ObjectCreator.new_attribute)foo>>> ObjectCreatorMirror = ObjectCreator # you can assign a class to a variable>>> print(ObjectCreatorMirror.new_attribute)foo>>> print(ObjectCreatorMirror())<__main__.ObjectCreator object at 0x8997b4c>

2. 動態建立類(Creating classes dynamically)

由於類是物件,所以你可以在任何地方建立它們,就像其他型別物件一樣。例如,在一個函式內通過class關鍵字建立類:>>> def choose_class(name):...if name == 'foo':...class Foo(object):...pass...            return Foo # return the class, not an instance...else:...class Bar(object):...pass...return Bar...>>> MyClass = choose_class('foo')>>> print(MyClass) # the function returns a class, not an instance<class '__main__.Foo'>>>> print(MyClass()) # you can create an object from this class<__main__.Foo object at 0x89c6d4c>但是這並不是動態地建立類,因為你還是需要把類的整體寫出來。既然類是物件,那麼它肯定是由什麼東西生成的。這就引出了元類——用來建立類的‘東西’

3.  元類是一個類(class)物件

普通的類定義了該類的例項物件所具有的屬性和方法,元類就定義了普通類所具有的屬性和方法。即例項物件是普通類的例項化,普通類是元類的例項化。如下圖所示:
Python中一切皆物件(object)。物件包括了數字(int), 字串(string), 函式(functions)和類(class)。這些物件都需要通過呼叫元類來構建,所以元類通常被用作類工廠(class-factory)。 例如,我們通過呼叫類來建立類的例項,python中通過呼叫元類來建立一個新的類。結合__init__和__new__方法,元類就允許你在建立新類是新增一些額外的內容,甚至是完全過載該類。除了類工廠外,元類還定義了類的型別(type),所以你可以用它來做更多的事情。例如,給元類定義一些常規的方法。元類中的方法(metaclass-method)就像是類方法(classmethod),所以你可以直接通過類名來呼叫這些方法,而不需要通過例項來呼叫。事實上,通過例項是無法呼叫元類中的方法的。這也是元類中方法與類方法的區別。

4.  __metaclass__屬性

當我們建立類時,可以在類的定義中新增__metaclass__屬性。屬性值是一些建立類的操作。class Foo(object):__metaclass__ = something...[...]