1. 程式人生 > >python:深度理解元類

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 三部曲:

  1. 攔截類的建立 (metaclass)

  2. 修改類 (在new裡面修改)

  3. 返回修改之後的類 (return class )

具體的詳情可以參考一下的連結:
深度理解python 元類