国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

How does it work - with_metaclass

testbird / 995人閱讀

摘要:先簡單介紹下中的元類。元類就是創建類的類,對于元類來說,類是它的實例,將返回。中的所有類,都是的實例,換句話說,是元類的基類。

我在看源代碼的時候,經常蹦出這一句:How does it work!竟然有這種操作?本系列文章,試圖剖析代碼中發生的魔法。順便作為自己的閱讀筆記,以作提高。

先簡單介紹下Python中的元類(metaclass)。元類就是創建類的類,對于元類來說,類是它的實例,isinstance(cls, metaclass)將返回True。Python中的所有類,都是type的實例,換句話說,type是元類的基類。使用type創建一個類的方法如下:

>>>type("MyClass", (), {})

type接受三個參數,第一個參數是類名稱,第二個參數是繼承的基類的元組,第三個參數是類的命名空間。上例中,我們創建了一個無基類(直接繼承object),無初始命名空間的類MyClass。

注:使用type創建的類和使用元類的類,都是新式類

使用元類后,該類將由定義的元類實例化來創建。定義的方法在Python 2與Python 3中有所不同:

# Python 2:
class MyClass(object):
    __metaclass__ = MyMeta

# Python 3:
class MyClass(metaclass=MyMeta):
    pass

如果你的項目需要兼容Python 2和Python 3,就需要使用一種方法,同時支持Python 2和Python 3。元類有兩個基本特性:

元類實例化得到類
元類能被子類繼承
根據這兩個特性,我們不難得到解決方案:

用元類實例化得到一個臨時類
定義類時繼承這個臨時類
我們可以寫出一個with_metaclass函數:

def with_metaclass(meta, *bases):
    """Compatible metaclass

    :param meta: the metaclass
    :param *bases: base classes
    """
    return meta("temp_class", bases, {})

# Testing:
class TestMeta(type):
    def __new__(cls, name, bases, d):
        d["a"] = "xyz"
        return type.__new__(cls, name, bases, d)


class Foo(object):pass

class Bar(with_metaclass(TestMeta, Foo)): pass

我們就創建了一個以TestMeta為元類,繼承Foo的類Bar。驗證:

>>> Bar.a
"xyz"
>>> Bar.__mro__
(, , , )

一切正常,但我們看到在Bar的mro里混進了一個臨時類temp_class,你忽略它吧,有時會很麻煩。作為完美主義者,我想尋找一種解決辦法,不要在mro中引入多余的類。

Python的six模塊專門為解決Python 2to3兼容問題而生,模塊里帶有一個with_metaclass函數,我們來看它是怎么實現的:(為了debug,添加了一個print語句)

def with_metaclass(meta, *bases):
    class metaclass(type):
        def __new__(cls, name, this_bases, d):
            print(cls, "new is called")
            return meta(name, bases, d)
    return type.__new__(metaclass, "temp_class", (), {})

# Testing:
class TestMeta(type):
    def __new__(cls, name, bases, d):
        d["a"] = "xyz"
        print(cls, "new is called")
        return type.__new__(cls, name, bases, d)

一時看不懂?沒關系,我們來用用看,為了看清楚過程,我們分成兩步執行:

>>> temp = with_metaclass(TestMeta, Foo)
>>> class Bar(temp): pass
...
.metaclass"> new is called
 new is called
>>> Bar.a
"xyz"
>>> Bar.__mro__
(, , )

我們明明生成了一個臨時類temp_class,但后來竟然消失了!下面來仔細分析函數的運行過程。首先我們看到,執行第一步生成臨時類時,兩個__new__都沒有調用,而第二步定義類時,兩個__new__都調用了。奧秘就在函數的返回語句return type.__new__(metaclass, "temp_class", (), {}),它創建了一個臨時類,具有如下屬性:

名稱為temp_class
是函數內部類metaclass的實例,它的元類是metaclass
沒有基類
創建時僅調用了type的__new__的方法
這是一個metaclass實例的不完全版本。接下來,定義Bar時,Bar得到繼承的元類metaclass,過程如下:

實例化metaclass
調用metaclass.__new__
返回meta(name, bases, d), meta=TestMeta,bases=(Foo,)
調用TestMeta.__new__實例化得到Bar
Bar的基類由第3步得到,于是就去除了temp_class,這其實用到了閉包,with_metaclass返回的臨時類中,本身無任何屬性,但包含了元類和基類的所有信息,并在下一步定義類時將所有信息解包出來。

以上就是with_metaclass源代碼的解析,通過這篇文章,相信能加深元類與閉包的理解。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/41088.html

相關文章

  • 從 Quora 的 187 個問題中學習機器學習和NLP

    摘要:許多的頂尖研究人員都會積極的在現場回答問題。雖然有許多主題的常見問題頁面比如,這是一個機器學習的,但是這些都是非常不全面的,或者不夠精致。在這篇文章中,我試圖做一個更加全面的有關機器學習和問題的。 作者:chen_h微信號 & QQ:862251340微信公眾號:coderpai簡書地址:http://www.jianshu.com/p/ac18... showImg(https:/...

    hidogs 評論0 收藏0
  • XML進階:Level 1 - XML簡介

    摘要:請注意,正斜杠位于結束標記中的標記描述之前。正斜杠必須在所有結束標簽之前,但標簽的語言必須與開頭標簽相同,上面的示例是。無論元素是否包含值,只要使用兩個標簽,開始和關閉標簽必須完全匹配,精確到大小寫除了結束標簽中的正斜杠。 By Rob Sheldon, 2014/03/26 (首次發表于: 2012/09/20) 關于系列 本文屬于進階系列:XML進階 自2003年以來,XML一直是...

    EddieChan 評論0 收藏0
  • [CS101] Programming Languages and OOP 編程語言及面向對象基礎題

    摘要:編程語言及面向對象基礎題 編程語言及面向對象基礎題 Design Pattern What is singleton? Whats its cons and pros? How to implement it?Definition: Singleton pattern is a design pattern that ensure that only one instance of a...

    Drinkey 評論0 收藏0
  • 《JavaScript Web應用開發》作者Nicolas:恰巧,愛好變職業(圖靈訪談)

    摘要:本文僅用于學習和交流目的,不得用于商業目的。今年,我們依然會組織。隨著語言的發展,這種情況將不再適用。本系列主要討論如何獲得這些高度模塊化的應用程序。這一系列內的后續圖書會討論測試及部署等內容。更多精彩,加入圖靈訪談微信 本文僅用于學習和交流目的,不得用于商業目的。非商業轉載請注明作譯者、出處,并保留本文的原始鏈接:http://www.ituring.com.cn/art... 訪談...

    wawor4827 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<