Python學習筆記__7.6章 使用原類
1、概覽
動態語言和靜態語言最大的不同,就是函數和類的定義,不是編譯時定義的,而是運行時動態創建的。
1.1、type()
class的定義是運行時動態創建的,而創建class的方法就是使用type()函數。
通過type()函數創建的類和直接寫class是完全一樣的,因為Python解釋器遇到class定義時,僅僅是掃描一下class定義的語法,然後調用type()函數創建出class。
type()函數既可以返回一個對象的類型,又可以創建出新的類型,比如,我們可以通過type()函數創建出Hello類:
>>> def fn(self, name='world'): # 先定義函數
... print('Hello, %s.' % name)
...
>>> Hello = type('Hello', (object,), dict(hello=fn)) # 創建Hello class
type()函數的3個參數:
class的名稱;
繼承的父類集合,註意Python支持多重繼承,如果只有一個父類,別忘了tuple的單元素寫法;
class的方法名稱與函數綁定,這裏我們把函數fn綁定到方法名hello上。
1.2、metaclass
除了使用type()動態創建類以外,要控制類的創建行為,還可以使用metaclass。
先定義metaclass,就可以創建類,最後可以創建實例
用metaclass給自定義的MyList類增加一個add方法:
# metaclass是類的模板,所以必須從`type`類型派生:
class ListMetaclass(type): # metaclass的類名總是以Metaclass結尾,以便清楚地表示這是一個metaclass
def __new__(cls, name, bases, attrs):
attrs['add'] = lambda self, value: self.append(value) # 為類創建了一個add方法
return type.__new__(cls, name, bases, attrs)
class MyList(list, metaclass=ListMetaclass): # 指示使用ListMetaclass來定制類,傳入關鍵字參數metaclass
pass
當我們傳入關鍵字參數metaclass時,魔術就生效了,它指示Python解釋器在創建MyList時,要通過ListMetaclass.__new__()來創建,在此,我們可以修改類的定義,比如,加上新的方法,然後,返回修改後的定義。
__new__()方法接收到的參數依次是:
當前準備創建的類的對象;
類的名字;
類繼承的父類集合;
類的方法集合。
什麽時候需要metaclass?
直接在MyList定義中寫上add()方法是更簡單。正常情況下,我們用不上metaclass。但是,總會遇到需要通過metaclass修改類定義的。ORM就是一個典型的例子。
ORM全稱“Object Relational Mapping”,即對象-關系映射,就是把關系數據庫的一行映射為一個對象,也就是一個類對應一個表,這樣,寫代碼更簡單,不用直接操作SQL語句。
Python學習筆記__7.6章 使用原類