python:深度理解元類
提出問題:
如何在一個類建立一個類呢?
首先我們的實現方式是這樣的, 看下以下程式碼:
class A : def create_class(self,user): if user=="company": class Company: def __str__(self): return "Company class" return Company if user=="school": class School: def __str__(self): return "Company class" return School a=A() Companyclass=a.create_class("company") company=Companyclass() print(company) # Company class
我們已經通過呼叫類的方法實現了 建立類,程式碼比較簡單,我不做解釋.不會的直接@我.
雖然我們實現了,但是程式碼量真是太大了. 我們再簡潔點也可以把 類A刪除掉,直接用方法就行了.
我們還有更好的方法直接建立類物件(類也是物件,方法和例項都可以稱為物件)
Type 動態建立類
我們一定知道了,當我們呼叫type(1) 這個方法,可以進行型別查詢. 它還有另外一個用法
就是建立類, 打個比喻 我們在做蛋糕, 必須用模板, 其中模板就是類,蛋糕是模板的例項.
但是蛋糕的模板 需要機器加工, 加工模板的機器就是 元類,它把模板當做機器的物件.
先看語法 :
Company=type(“類名稱”,(繼承的基類),{類的屬性 })
Company=type("Company",(),{})
print(Company) # <class '__main__.Company'>
已經完成了 類的建立,只是繼承的基類和 類的屬性 全部為空.
我們再進一步擴充套件新增一些屬性
Company=type("Company",(),{"name":"ebaotech","Adress":"楊浦區"})
co=Company()
print(co.name,co.Adress) #ebaotech 楊浦區
有細心的小夥伴該說了,類有屬性也有方法, 怎麼新增方法呢
我們就添加個方法試試 :
def run(self):
return "i am running"
Company=type("Company",(),{"name":"ebaotech","Adress":"楊浦區","run":run})
co=Company()
print(co.name,co.Adress,co.run())
解釋要點
1.run 方法裡必須有self ,不然用物件呼叫會找不到
2.“run”:run ,這個run 不要寫成 run()的形式
新增繼承基類
class Baseclass:
def say(self):
print("basecalss say")
def run(self):
return "i am running"
Company=type("Company",(Baseclass,),{"name":"ebaotech","Adress":"楊浦區","run":run})
co=Company()
co.say() #basecalss say
注意點 在新增繼承類的時候,Baseclass 後邊要有逗號,否則會報錯.
自己寫的平常的類,和type 生成的類實際都是一樣的,平常的類也是會用type生成的.
這樣就完成了, 又引出一個概念,什麼是元類
元類就是建立類的類 ,剛才的type 就是一個元類.
解釋下:既然我們已經介紹了,類也是物件 ,那誰去建立類物件呢,只能用元類.
元類控制過程
控制類物件生成過程用的是 metaclass 這個是在類物件生成之前進行的動作.
class Metaclass(type):
pass
class A(metaclass=Metaclass):
pass
為什麼會控制類例項化過程呢 請看下邊的解釋.
Python做了如下的操作:
A中有metaclass這個屬性嗎?如果是,Python會在記憶體中通過__metaclass__建立一個名字為Foo的類物件(我說的是類物件,請緊跟我的思路)。如果Python沒有找到__metaclass__,它會繼續在Metaclass(父類)中尋找__metaclass__屬性,並嘗試做和前面同樣的操作。如果Python在任何父類中都找不到__metaclass__,它就會在模組層次中去尋找__metaclass__,並嘗試做同樣的操作。如果還是找不到__metaclass__,Python就會用內建的type來建立這個類物件。
一句話就是類裡有 metaclass 就是執行metaclass 類,實在找不到就用type 去生成 .
現在的問題就是,你可以在__metaclass__中放置些什麼程式碼呢?答案就是:可以建立一個類的東西。那麼什麼可以用來建立一個類呢?type,或者任何使用到type或者子類化type的東東都可以, metaclass 也是繼承type .
自定義元類
請記住,'type’實際上是一個類,就像’str’和’int’一樣
所以,你可以從type繼承
class Metaclass(type):
def __new__(cls, *args, **kwargs):
return super().__new__(cls, *args, **kwargs)
class A(metaclass=Metaclass):
def __init__(self,name):
self.name=name
def __str__(self):
return " i love you "
a=A("Tengfei")
print(a) # i love you
class A 類物件操作實現委託給了 metaclass.
但就元類本身而言,它們其實是很簡單, metaclass 三部曲:
-
攔截類的建立 (metaclass)
-
修改類 (在new裡面修改)
-
返回修改之後的類 (return class )
具體的詳情可以參考一下的連結:
深度理解python 元類