元類
什麼是元類?
答:類的類。
如何理解?可以這樣說,我們用類來創建一個實例對象如myObject = MyClass()
。事實上Python中的類也是對象(萬物皆對象),所以類也需要通過類的類創建,如MyClass = MetaClass()
。這個類的類(MetaClass)就是元類。
元類從哪來
通常我們用type(object)
來獲取一個對象的類型,如:
>>> type(512)
<class 'int'>
>>> type("zhong")
<class 'str'>
然而type()還有另一個用處:type(name, bases, dict) -> a new type
,也就是用來創建一個類。一般我們都是通過class
關鍵字來定義一個類:
class MyClass(object):
pass
但也可以用type動態創建一個類:
>>> MyClass = type("MyClass", (), {})
>>> myObject = MyClass()
其實type就是一個元類。Python中所有類都是通過type來創建的。我們可以通過__class__來驗證:
>>> str.__class__
<class 'type'>
>>> int.__class__
<class 'type'>
>>> object.__class__
<class 'type'>
我們自己用class
定義出來的類也是如此:
>>> class MyClass(object):
pass
>>> myObject = MyClass()
>>> myObject.__class__.__class__
<class 'type'>
type的用法
函數接口:type(name, bases, dict)
- name:類名
- bases:基類,接收一個元組
- dict:綁定類的方法和屬性
現在通過類比的方式來理解type()的使用。
第一種:利用class關鍵字定義類
class MyClass(object):
def __init__(self):
self.string = "this is a test class"
def print_str(self):
print(self.string)
if __name__ == "__main__":
myObject = MyClass()
print(myObject.string)
myObject.print_str()
# 輸出:
#this is a test class
#this is a test class
第二種:利用type創建類
string = "this is a test class"
def print_str(self):
print(self.string)
MyClass = type(
"MyClass",
(object,),
dict(string=string, print_str=print_str))
if __name__ == "__main__":
myObject = MyClass()
print(myObject.string)
myObject.print_str()
# 輸出:
#this is a test class
#this is a test class
創建類的過程
當我們用如下方法
class MyClass(object):
pass
Python做了這樣的操作:(1)在MyClass中尋找metaclass,如果存在,用它來創建名MyClass的類對象;(2)如果不存在,就去父類(這裏是object)中找;(3)最後都沒找到,利用Python內置的type()創建這個類對象
注: 在Python2中,如果沒在父類中找到metaclass會去模塊層次中尋找,但似乎Pythony3裏取消了,這裏留疑
metaclass的使用
比如,我們想給自己定義的類添加author屬性,即所有實例化的對象都可以執行語句:a.author
來獲取作者信息,實現代碼如下:
def upper_attr(name, bases, attrs):
# 增加author信息
attrs.update({"author":"Guan"})
# 返回一個類的類
return type(name, bases, attrs)
# metaclass的使用方法
class MyClass(object, metaclass=upper_attr):
pass
if __name__ == "__main__":
myObj = MyClass()
print(myObj.author)
# 輸出:
#Guan
事實上,更建議metaclass對接一個自定義的元類,而不是函數
# 需要繼承自type
class MyMetaClass(type):
def __new__(cls, name, bases, attrs):
attrs.update({"author":"Guan"})
return super().__new__(cls, name, bases, attrs)
class MyClass(object, metaclass=MyMetaClass):
pass
if __name__ == "__main__":
myObj = MyClass()
print(myObj.author)
# 輸出
#Guan
元類的作用
元類的主要目的就是爲了當創建類時能夠自動地改變類。正如我前邊的列子,創建的每一個類都能夠自動添加author屬性。