Python進階:一步步理解Python中的元類metaclass
雖然Python本身很難說是面向對象語言,但Python中的數據模型可以說真的是“純面向對象”。在Python的世界里,一切皆是對象。無論是數值、字符串、序列、字典、函數、模塊、類、實例、文件等等。
元類(metaclass)是Python 2.2中引入的概念,它的作用是定制類的創建行為。這么解釋可能有點難理解,那么這篇文章就通過實例,一步步解釋Python中的元類。
1. Python中一切皆對象,包括類
class Foo:
def hello(self):
print("hello world!")
return
foo = Foo()
print(type(foo)) # <class '__main__.Foo'>
print(type(foo.hello)) # <class 'method'>
print(type(Foo)) # <class 'type'>
temp = Foo # 賦值給其他變量
Foo.var = 11 # 增加參數
print(Foo) # 作為函數參數
例子中type(Foo)說明Foo本身也是一個對象,可以將其賦值給其他對象、對其添加屬性、將其作為函數參數傳遞等等。
2. 類的創建過程
在上邊的例子中,類Foo的創建過程中會執行class語句,此時需要首先確定元類(元類定制類的創建行為)。元類的確定過程如下:
- 確定類Foo的父類是否有參數metaclass,如果沒有則:
- 確定類Foo的父類的父類是否有參數metaclass,如果沒有則:
- 使用默認元類type(type的用法會在3中講解)。
上邊的例子中,前三項都不符合,則直接使用默認元類type。即上邊的語句相當于:
def hello(self):
print("hello world")
return
Foo = type("Foo", (object,), {"hello": hello})
此時可以看出,實際上類Foo是元類type的實例。參見文章的封面圖。
3. 動態創建類
Python中的類可以動態創建,用的就是默認元類type。動態創建類的type函數原型為:
type(object_or_name, bases, dict)
這里不過多贅述,上個章節中有介紹。舉個比較復雜的動態創建類的例子:
def init(self, name):
self.name = name
return
def hello(self):
print("hello %s" % self.name)
return
Foo = type("Foo", (object,), {"__init__": init, "hello": hello, "cls_var": 10})
foo = Foo("xianhu")
print(foo.hello())
print(Foo.cls_var)
4. 自定義元類
再一次說明實例、類和元類之間的關系:
>>> foo.__class__ # <class 'Foo'>
>>> Foo.__class__ # <class 'type'>
>>> type.__class__ # <class 'type'>
foo是Foo的實例,Foo是type的實例,type的類又是type。type是默認的元類。那么如何自定義元類呢?(注意,百分之99的工程中不會用到自定義元類,除非你對元類非常理解)
舉個例子,假設我們需要對一個模塊中的所有函數添加作者屬性。首先自定義一個元類,自定義時,需要繼承默認元類type,并重寫其中的__new__方法:
class Author(type):
def __new__(mcs, name, bases, dict):
# 添加作者屬性
dict["author"] = "xianhu"
return super(Author, mcs).__new__(mcs, name, bases, dict)
對模塊中所有函數的繼承類參數中添加metaclass參數:
class Foo(object, metaclass=Author):
pass
foo = Foo()
print(foo.author)
注意:Python3中不再有__metaclass__屬性以及模塊級別的__metaclass__屬性。如果一個模塊中函數較多,可以利用正則表達式進行查找替換。
不過在平時的使用中,我發現了模塊級別有個__build_class__函數,將其改為Author,就能達到模塊級別元類的效果。但具體有哪些副作用還不太清楚,慎用!!!
后再強調一遍:
Metaclasses are deeper magic that 99% of users should never worry about. If you wonder whether you need them, you don't (the people who actually need them know with certainty that they need them, and don't need an explanation about why).
來自:https://zhuanlan.zhihu.com/p/23887627