[Advanced Python] 15 - "Metaclass": ORM

From: 使用元類app

動態建立類

與靜態語言最大的不一樣,就是函數和類的定義,不是編譯時定義的,而是運行時動態建立的。函數

一 、type()動態建立

咱們說class的定義是運行時動態建立的;測試

建立class的方法就是使用type()函數。spa

type()函數既能夠返回一個對象的類型,又能夠建立出新的類型。code

 

問題來了:type建立了一個類?如何理解。如下即是一個 「動態建立」 的過程。對象

>>> 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)) <class 'type'> >>> print(type(h)) <class '__main__.Hello'>

 

 

2、metaclass

要控制類的建立行爲,還能夠使用metaclass。blog

metaclass,直譯爲元類,簡單的解釋就是:先定義metaclass,就能夠建立類,最後建立實例。get

因此,metaclass容許你建立類或者修改類。換句話說,你能夠把「類」當作是metaclass建立出來的「實例」編譯

metaclass是Python面向對象裏最難理解,也是最難使用的魔術代碼。模板

 

神奇之處

正常狀況下,你不會碰到須要使用metaclass的狀況。

[實驗]:經過metaclass給咱們自定義的MyList增長一個add方法。

定義ListMetaclass,按照默認習慣,metaclass的類名老是以Metaclass結尾,以便清楚地表示這是一個metaclass:

# metaclass是類的模板,因此必須從`type`類型派生:
classListMetaclass(type):
    def __new__(cls, name, bases, attrs):
        attrs['add'] = lambda self, value: self.append(value)  # 添加了add方法 return type.__new__(cls, name, bases, attrs)

 

 

有了ListMetaclass,咱們在定義類的時候還要指示使用ListMetaclass來定製類,傳入關鍵字參數metaclass

class MyList(list, metaclass=ListMetaclass):
    pass

 

測試了一下,MyList能夠調用add方法。

>>> L = MyList()
>>> L.add(1)
>> L
[1]

 

 

動態修改有什麼意義?

直接在MyList定義中寫上add()方法不是更簡單嗎?正常狀況下,確實應該直接寫,經過metaclass修改純屬變態。

可是,總會遇到須要經過metaclass修改類定義的。ORM就是一個典型的例子。

 

/* implement */

 

 

 

 

End.

相關文章
相關標籤/搜索