Python中的元類(metaclass)


推薦+收藏:深刻理解Python中的元類(metaclass)

做一些筆記學習學習:

在大多數編程語言中,類就是用來描述如何生成一個對象的代碼段,在Python中類也是一個對象,這個(類)對象自身擁有創建對象(類實例)的能力。

因為它的本質是一個對象:

  • 可以將它賦值給一個變量
  • 可以拷貝它
  • 增加屬性
  • 作為參數進行傳遞
  • 可以在運行時動態地創建他們,可以在函數中創建類,只需要使用class關鍵字即可

當使用class關鍵字的時候,Python解釋器會自動地創建這個對象,Python還提供了手動處理的方法:type()

type是一個生成類對象的類工廠,實際上也是一個類,專門構建類對象的類稱為元類:

查看type的幫助信息如下:

Init signature: type(self, /, *args, **kwargs)
Docstring:     
type(object_or_name, bases, dict)
type(object) -> the object's type
type(name, bases, dict) -> a new type
Type:           type

1.第一示例,傳入一個對象的時候,返回得是這個對象的Type類型信息,用於知道一個對象的類型是什么

2.第二個示例,傳入的是類對象的信息,生成一個類對象,name為類名,bases為繼承的父類,dict為屬性字典,用於動態創建類

__metaclass__屬性

可以在為類添加一個__metaclass__屬性,在PEP 3115中元類的生命語法發生變化,通過在在基類的列表中指定metaclass關鍵字,例如:class Foo(base1, base2, metaclass=mymeta):pass

class Foo(object):
    __metaclass__=something

當解釋器解析后class Foo(object),類對象Foo並沒有創建,Python會在類定義中尋找__metaclass__屬性,用它創建,如果找到了,Python就會用它來創建Foo,沒有就會使用type來創建。

class Foo(Bar):
    pass

如果Foo沒有__metaclass__屬性,會繼續父類Bar中遞歸地繼續尋找__metaclass__屬性,嘗試之前操作。

下面types.py中源碼,PEP 3115做出修改,提供了一個new_class用metaclass來動態地創建一個類對象,其中_calculate_meta函數用於計算衍生擴展最深的元類:

def _calculate_meta(meta, bases):
    """Calculate the most derived metaclass."""
    winner = meta
    for base in bases:
        base_meta = type(base)
        if issubclass(winner, base_meta):
            continue
        if issubclass(base_meta, winner):
            winner = base_meta
            continue
        # else:
        raise TypeError("metaclass conflict: "
                        "the metaclass of a derived class "
                        "must be a (non-strict) subclass "
                        "of the metaclasses of all its bases")
    return winner

從上述代碼可以看出對類對象每個基類都進行了判斷比較,找出擴展最深的元類(winner)。

就元類本身而言,他們其實很簡單:

  1. 攔截類的創建
  2. 修改類
  3. 返回修改之后的類


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM