成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Python: metaclass小記

mushang / 1481人閱讀

摘要:最前面那個(gè),解釋器實(shí)際的流程是解析這段代碼,得知它需要?jiǎng)?chuàng)建一個(gè)類對(duì)象,這個(gè)類的名字叫做它的父類列表用表示是,它的屬性用一個(gè)來(lái)表示就是。解決方法很簡(jiǎn)單關(guān)鍵就是前面被特別標(biāo)記了的應(yīng)當(dāng)返回這個(gè)的父類的方法返回的對(duì)象。

(原發(fā)于我的blog:Python: metaclass小記 )

友情提示:本文不一定適合閱讀,如果執(zhí)意要讀,請(qǐng)備好暈車(chē)藥。

題記

"Metaclasses are deeper magic than 99% of users should ever worry about. If you wonder whether you need them, you don"t."

-- Tim Peters

起因

這句話聽(tīng)起來(lái)就很誘人,曾經(jīng)試圖去理解它,但是因?yàn)闆](méi)有實(shí)際的需求,就因?yàn)闊X子而放棄了。不妨摘錄一段Python document里關(guān)于metaclass的概述,簡(jiǎn)直就是繞口令:

Terminology-wise, a metaclass is simply "the class of a class". Any class whose instances are themselves classes, is a metaclass. When we talk about an instance that"s not a class, the instance"s metaclass is the class of its class: by definition, x"s metaclass is x.__class__.__class__. But when we talk about a class C, we often refer to its metaclass when we mean C.__class__ (not C.__class__.__class__, which would be a meta-metaclass; there"s not much use for those although we don"t rule them out).

昨天心血來(lái)潮想寫(xiě)一個(gè)帶class initializer的class,發(fā)現(xiàn)繞不過(guò)metaclass了,于是又翻出來(lái)看。

概述

其實(shí)是要理解metaclass的本質(zhì),無(wú)非是要時(shí)刻牢記兩點(diǎn):1. Python中一切皆對(duì)象; 2. class也是一個(gè)對(duì)象,它的class就是metaclass。

舉例來(lái)說(shuō):

class A(object): pass
a = A()
print (a, id(a), type(a))

(<__main__.A object at 0xb183d0>, 11633616, )

print (A, id(A), type(A))

(, 11991040, )

print (type, id(type), type(type))

(, 1891232, )

其中第一個(gè)print很好理解:a是一個(gè)A的實(shí)例,有自己的id(其實(shí)就是內(nèi)存地址)、a的class是A。

第二個(gè)print就有點(diǎn)燒腦子了:A是一個(gè)class,也有自己的id(因?yàn)锳也是一個(gè)對(duì)象,雖然print出來(lái)的時(shí)候沒(méi)有明確說(shuō)),A的class是type。

而第三個(gè)就暈乎了:type是一個(gè)type,也有自己的id(因?yàn)閠ype也是一個(gè)對(duì)象),type的class是type,也就是它自己。

再回想上面提到的兩點(diǎn):A是一個(gè)對(duì)象,它的class是metaclass。也就是說(shuō) type 是一個(gè)metaclass,而A類是type類的一個(gè)對(duì)象。

唉,本來(lái)想好好解釋的,沒(méi)想到還是說(shuō)成繞口令了。算了,反正我懂了,繼續(xù)。

type

沒(méi)有仔細(xì)了解type是什么的同學(xué)可能會(huì)以為type是一個(gè)函數(shù):type(X)用于返回X的類對(duì)象。

然而并不完全是這樣的:在python里,X(args)可能是調(diào)用一個(gè)函數(shù),也可能是在實(shí)例化一個(gè)X的對(duì)象——而很不幸地,type(X)實(shí)際上是介于二者之間的一個(gè)調(diào)用:雖然type是一個(gè)class,但是它的__call__方法是存在的,于是python把它當(dāng)成一個(gè)函數(shù)來(lái)調(diào)用,實(shí)際調(diào)用到了源碼中的type_call;type_call調(diào)用了type.__new__試圖初始化一個(gè)type類的實(shí)例,然而type.__new__(位于源碼中的type_new函數(shù))發(fā)現(xiàn)臥槽居然只有一個(gè)參數(shù),于是就返回了這個(gè)參數(shù)的type(源碼是這么寫(xiě)的:"return (PyObject *) Py_TYPE(x);",并沒(méi)有生成新的對(duì)象)。也就是說(shuō),本來(lái)是個(gè)函數(shù)調(diào)用,里面卻是要初始化一個(gè)對(duì)象,然而最后返回的卻不是初始化的對(duì)象!尼瑪那個(gè)特殊情況為毛不放到函數(shù)調(diào)用里面啊,開(kāi)發(fā)者腦抽了嗎!

感到腦抽的同學(xué)可以暫時(shí)忽略上面那段話,跟本文沒(méi)太大關(guān)系。繼續(xù)。

實(shí)際上type是在builtin模塊中定義,指向源碼中PyType_Type對(duì)象的一個(gè)引用:

//位于Python/bltinmodule.c
PyObject * _PyBuiltin_Init(void)
{
    ...
    SETBUILTIN("type",                  &PyType_Type);
    ...
}

這個(gè)PyType_Type又是個(gè)什么鬼?好吧,繼續(xù)貼源碼

//位于Objects/typeobject.c
PyTypeObject PyType_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "type",                                     /* tp_name */
    ...
    type_init,                                  /* tp_init */
    0,                                          /* tp_alloc */
    type_new,                                   /* tp_new */
    ...
};

注意3點(diǎn):

PyType_Type,也就是python里的type,是在源碼中生成的一個(gè)對(duì)象;這個(gè)對(duì)象的類型是PyTypeObject,所以它恰好又是一個(gè)類,至于你信不信,反正我信了。后面我把它叫做類對(duì)象,注意:不是類的對(duì)象,而是類本身是一個(gè)對(duì)象。

PyVarObject_HEAD_INIT遞歸引用了自己(PyType_Type)作為它的type(在源碼中,指定某個(gè)對(duì)象的type為X,就是指定了它在python環(huán)境中的class為X),所以前面第三個(gè)print中可以看到,type(type) == type(哈哈哈,寫(xiě)繞口令真好玩)

在PyType_Type的定義指定了 tp_init = type_init 和 tp_new = type_new 這兩個(gè)屬性值。這是兩個(gè)函數(shù),也位于源碼中的Object/typeobject.c。

關(guān)于第3點(diǎn),在Python document中關(guān)于__new__方法的說(shuō)明里有詳細(xì)的介紹,這里簡(jiǎn)單總結(jié)一下:在new一個(gè)對(duì)象的時(shí)候,只會(huì)調(diào)用這個(gè)class的__new__方法,它需要生成一個(gè)object、調(diào)用這個(gè)對(duì)象的__init__方法對(duì)它進(jìn)行初始化,然后返回這個(gè)對(duì)象。

好吧,我發(fā)現(xiàn)不得不把簡(jiǎn)單總結(jié)展開(kāi),否則確實(shí)說(shuō)不清楚。

實(shí)例化

這是一個(gè)很有意思的設(shè)計(jì):把實(shí)例化的流程暴露給碼農(nóng),意味著碼農(nóng)可以在對(duì)象的生成前、生成后返回前兩個(gè)環(huán)節(jié)對(duì)這個(gè)對(duì)象進(jìn)行修改(【甚至】在__new__方法中生成并返回的對(duì)象并沒(méi)有強(qiáng)制要求一定是該class的實(shí)例!不過(guò)在document里建議,如果要覆蓋__new__方法,那么【應(yīng)當(dāng)】返回這個(gè)class的父類的__new__方法返回的對(duì)象)。這里還有一個(gè)非常tricky的地方:雖然沒(méi)有明確指定,但是__new__方法被硬編碼為一個(gè)staticmethod(有興趣的話可以去翻type_new函數(shù)),它的第一個(gè)參數(shù)是需要被實(shí)例化的class,其余參數(shù)則是需要傳給__init__的參數(shù)。

說(shuō)起來(lái)非??菰?,還是舉一個(gè)例子吧,就用document里給出的Singleton:

class Singleton(object):
    def __new__(cls, *args, **kwargs):
        it = cls.__dict__.get("__it__")
        if it is not None:
            return it
        cls.__it__ = it = object.__new__(cls) #注意
        it.__init__(*args, **kwargs)
        return it

    def __init__(self, *args, **kwargs):
        pass

class DbConnection(Singleton):
    def __init__(self, db_config):
        self._connection = AnyHowToConnectBy(db_config)
        
conn = new DbConnection(db_config)

代碼并不復(fù)雜,但是可能有點(diǎn)玄乎,需要理解一下那個(gè)cls參數(shù),前面說(shuō)了,它是需要被實(shí)例化的class,也就是說(shuō),最后一行實(shí)際執(zhí)行的是:

DbConnection.__new__(DbConnection, db_config)

而DbConnection的__new__方法直接繼承于Singleton, 所以實(shí)際調(diào)用的是

Singleton.__new__(DbConnection, db_config)

主要注意的地方,在上面這段代碼的第六行,Singleton是繼承于object(這里特指python中的那個(gè)object對(duì)象),因此調(diào)用了object.__new__(DbConnection)來(lái)生成一個(gè)對(duì)象,生成過(guò)程位于C源碼中的object_new函數(shù)(Objects/typeobject.c),它會(huì)將新生成對(duì)象的type指定為DbConnection,然后直接返回。

Singleton.__new__在拿到了生成的DbConnection實(shí)例以后,將它保存在了DbConnection類的__it__屬性中,然后對(duì)該實(shí)例進(jìn)行初始化,最后返回。

可以看到,任何繼承于Singleton類的子類,只要不覆蓋其__new__方法,每個(gè)類永遠(yuǎn)只會(huì)被實(shí)例化一次。

好了,第2點(diǎn)暫告一段落,接下來(lái)回歸正題,尼瑪我都快忘了要講的是metaclass啊。

metaclass

還記的上面可以暫時(shí)忽略的那段話嗎?type(X)是試圖實(shí)例化type對(duì)象,但是因?yàn)橹挥幸粋€(gè)參數(shù),所以源碼中只是返回了X的類。而type的標(biāo)準(zhǔn)初始化參數(shù)應(yīng)當(dāng)有三個(gè):class_name, bases, attributes。最前面那個(gè)"class A(object): pass",python解釋器實(shí)際的流程是:

解析這段代碼,得知它需要?jiǎng)?chuàng)建一個(gè)【類對(duì)象】,這個(gè)類的名字叫做"A", 它的父類列表(用tuple表示)是 (object,),它的屬性用一個(gè)dict來(lái)表示就是 {} 。

查找用于生成這個(gè)類的metaclass。(終于講到重點(diǎn)了有木有?。?
查找過(guò)程比較蛋疼,位于Python/ceval.c : build_class函數(shù),按順序優(yōu)先采用以下幾個(gè):

2.1 定義中使用 __metaclass__ 屬性指定的(本例:沒(méi)有)
2.2 如果有父類,使用第一個(gè)父類的 __class__ 屬性,也就是父類的metaclass(本例:object的class,也就是type)
2.2.1 如果第一個(gè)父類沒(méi)有 __class__ 屬性,那就用父類的type(這是針對(duì)父類沒(méi)有父類的情況)
2.3 使用當(dāng)前Globals()中的 __metaclass__ 指定的(本例:沒(méi)有,不過(guò)2.2里已經(jīng)找到了)
2.4 使用PyClass_Type

注:2.2.1和2.4中提到了沒(méi)有父類,或者父類沒(méi)有父類的情形,這就是python中的old-style class,在python2.2之前所有的對(duì)象都是這樣的,而2.2之后可以繼承于object類,就變成了new-style class。這種設(shè)計(jì)保持了向后兼容。

使用metaclass來(lái)創(chuàng)建這個(gè)A類。由于A類的class就是metaclass,所以這個(gè)過(guò)程其實(shí)就是實(shí)例化metaclass的過(guò)程。本例中找到的metaclass是type,所以最終python執(zhí)行的相當(dāng)于這一句:

type("A", (object,), {})

再回想一下前面提到的實(shí)例化過(guò)程,實(shí)際上這一句分成兩步: 1. 調(diào)用type.__new__(type, "A", (object,), {})生成type的一個(gè)實(shí)例(也就是A類對(duì)象);2. 調(diào)用type.__init__(A, "A", (object,), {}) 對(duì)A類對(duì)象進(jìn)行初始化。注意:這里調(diào)用的是type.__init__,而不是A.__init__:因?yàn)锳是type的一個(gè)實(shí)例。

流程終于解釋完啦,不過(guò)我覺(jué)得還是舉個(gè)栗子會(huì)比較好。就用我看到的那個(gè)有點(diǎn)二二的栗子吧:定義一個(gè)class,把它的所有屬性都改成全大寫(xiě)的。我感覺(jué)這個(gè)栗子唯一的作用就是用來(lái)當(dāng)栗子了。還好還有這個(gè)作用,否則連出生的機(jī)會(huì)都沒(méi)有。

栗子

直接上代碼好了:

def upper_meta(name, bases, attrs):
    new_attrs = {}
    for name, value in attrs.items():
        if not name.startswith("__"):
            new_attrs[name.upper()] = value
        else:
            new_attrs[name] = value
    return type(name, bases, new_attrs)

class Foo(object):
    __metaclass__ = upper_meta
    hello = "world"

print Foo.__dict__

請(qǐng)不要說(shuō)“說(shuō)好的metaclass呢!怎么變成了一個(gè)函數(shù)!我摔!”,回顧一下最最前面提到的一點(diǎn):everything is an object in python。upper_meta作為一個(gè)函數(shù),它也是一個(gè)對(duì)象啊。而metaclass也不過(guò)就是個(gè)對(duì)象,并沒(méi)有本質(zhì)上的差別——只要它被call的時(shí)候能接受name, bases, attrs這三個(gè)參數(shù)并返回一個(gè)類對(duì)象就行了。duck-typing的語(yǔ)言用起來(lái)就是有這樣的一種不可言狀的酸爽感。

理解了這一點(diǎn),這段代碼就能理解了,upper_meta返回了一個(gè)type類的實(shí)例——也就是Foo類,并且可以看到print出來(lái)的屬性里頭只有HELLO而沒(méi)有hello。

考慮到可能有人不滿意,想看使用class來(lái)作為metaclass的情形,我就勉為其難換個(gè)姿勢(shì)再舉一下這個(gè)栗子(真累)。

class upper_meta(type):
    def __new__(cls, name, bases, attrs):
        attrs = dict([(n if n.startswith("__") else n.upper(), v) for n, v in attrs.items()])
        return type(name, bases, attrs)

寫(xiě)的太長(zhǎng)了,換了一個(gè)短一點(diǎn)的oneliner,但是效果不變(其實(shí)我就是想炫一下,不服來(lái)咬我呀)。

這段代碼雖然形式上跟前面的upper_meta函數(shù)不一樣,但是本質(zhì)是一樣的:調(diào)用了upper_meta("Foo", (object,), {"hello": "world"}),生成了一個(gè)新的名為Foo的類對(duì)象。

理論上,故事講到這里應(yīng)該結(jié)束了,然而我想說(shuō),壓軸戲還沒(méi)上呢。

壓軸戲

我要把這栗子舉得更高更遠(yuǎn),也更符合實(shí)際開(kāi)發(fā)的需求:繼承。

class Bar(Foo):
    hi = "there"

print Bar.__dict__

這段代碼太簡(jiǎn)單了,但是埋在下面的邏輯卻太復(fù)雜了。

它的輸出并不是{"HI": "there"}, 而是{"hi": "there"}。你print Bar.HELLO, Bar.__metaclass__都能得到預(yù)期的輸出,但是偏偏沒(méi)有HI,只有hi。

為什么?這真是個(gè)燒腦細(xì)胞的事情。我已經(jīng)把所有的邏輯都展現(xiàn)出來(lái)了,甚至還做了特別的標(biāo)記。然而即便如此,想要把這個(gè)邏輯理順,也是一件非常有挑戰(zhàn)性的事情,幸好我已經(jīng)想明白了:苦海無(wú)涯,回頭是岸。啊呸,應(yīng)該是——學(xué)海無(wú)涯苦作舟,不想明白不回頭。

我想說(shuō)“甚至還做了特別標(biāo)記”這句話的意思是,我還給【甚至】這兩個(gè)字做了特別標(biāo)記:在__new__方法中生成并返回的對(duì)象并沒(méi)有強(qiáng)制要求一定是該class的實(shí)例!

問(wèn)題的關(guān)鍵就在這里:前面兩個(gè)栗子中給出的upper_meta,返回的并不是upper_meta的實(shí)例,而是type的實(shí)例,而是type的實(shí)例,而是type的實(shí)例。重說(shuō)三。

什么意思?再看看代碼,最后return的是type(name, bases, attrs),也就是說(shuō),F(xiàn)oo類對(duì)象并不是upper_meta的實(shí)例,而是type的實(shí)例(也就是說(shuō):雖然指定并被使用的metaclass是upper_meta,但是最終創(chuàng)建出來(lái)的Foo類的metaclass是type)。不信你print type(Foo)試試,結(jié)果就是type,而不是upper_meta。

為什么這會(huì)導(dǎo)致繼承于Foo類的Bar類不能由upper_meta來(lái)搭建?Bar.__metaclass__不還是upper_meta嗎?

這個(gè)問(wèn)題就沒(méi)有那么困難了,有興趣的同學(xué)可以自己試著分析一下,沒(méi)興趣的大概也不會(huì)有耐心看到這里吧。

Bar.__metaclass__并不是Bar的原生屬性,而是繼承于Foo的——所以在print Bar.__dict__的時(shí)候看不到__metaclass__。也就是說(shuō),在試圖創(chuàng)建Bar時(shí),attrs里并沒(méi)有__metaclass__屬性,所以并不會(huì)直接采用upper_meta。再回顧一下選擇metaclass的順序就可以發(fā)現(xiàn),實(shí)際上在2.2里會(huì)選擇Foo的metaclass——Foo的metaclass是type,而不是指定的upper_meta。

解決方法很簡(jiǎn)單:關(guān)鍵就是前面被特別標(biāo)記了的【應(yīng)當(dāng)】返回這個(gè)class的父類的__new__方法返回的對(duì)象。具體到代碼應(yīng)當(dāng)是這樣:

class upper_meta(type):
    def __new__(cls, name, bases, attrs):
        attrs = dict([(n if n.startswith("__") else n.upper(), v) for n, v in attrs.items()])
        return super(upper_meta, cls).__new__(cls, name, bases, attrs)

    def __init__(cls, name, bases, attrs):
        print >>sys.stderr, "in upper_meta.__init__" #FOR TEST ONLY

新增的__init__方法并不是必須的,有興趣的同學(xué)可以跟上面的栗子對(duì)比一下,由于前面返回的是type類的實(shí)例,調(diào)用到的是type.__init__;而這樣正確的寫(xiě)法就會(huì)調(diào)用到upper_meta.__init__。(p.s. super也是燒腦細(xì)胞的東西,但用于解決鉆石繼承的問(wèn)很有意思,有興趣的同學(xué)可以看看Cooperative methods and "super")

果然很燒腦細(xì)胞吧。

關(guān)于metaclass的選擇,還有另外一個(gè)坑:在metaclass 2.3提到了,找不到metaclass的情況下,會(huì)使用Globals()中定義的__metaclass__屬性指定的元類來(lái)創(chuàng)建類,那么為什么下面的代碼卻沒(méi)有生效呢?

def __metaclass__(name, bases, attrs):
    attrs = dict([(n if n.startswith("__") else n.upper(), v) for n, v in attrs.items()])
    return type(name, bases, attrs)

class Foo(object):
    hello = "world"

print Foo.__dict__
class initializer

回到我最初的需求:我需要?jiǎng)?chuàng)建帶class initializer的類。為什么會(huì)有這樣的需求?最常見(jiàn)的metaclass的應(yīng)用場(chǎng)景是對(duì)數(shù)據(jù)庫(kù)的封裝。舉例來(lái)說(shuō),我希望創(chuàng)建一個(gè)Table類,所有表都是繼承于這個(gè)類,同時(shí)我還想給每一個(gè)表都設(shè)置一個(gè)緩存dict(使用主鍵作為key緩存查詢結(jié)果)。一個(gè)很自然的想法是這樣的:

class Table(object):
    _pk_cache = {}
    
    @classmethod
    def cache(cls, obj):
        cls._pk_cache[obj.pkey()] = obj;
        
    @classmethod
    def findByPk(cls, pkey):
        return cls._pk_cache[pkey]

    def __init__(self, pkey, args):
        self._pkey = pkey
        self._args = args
        type(self).cache(self)
        
    def pkey(self):
        return self._pkey

    def __repr__(self):
        return type(self).__name__ + ":" + repr(self._args)
        
class Student(Table):
    pass
    
class Grade(Table):
    pass
    
s1 = Student(1, "s1")
g1 = Grade(1, "g1")

print Student.findByPk(1)

可惜這是錯(cuò)的。從輸出結(jié)果就能看出來(lái),返回的是一個(gè)Grade對(duì)象,而不是預(yù)期的Student對(duì)象。原因很簡(jiǎn)單:子類們并不直接擁有_pk_cache ,它們?cè)L問(wèn)的是Table的_pk_cache ,而該dict只被初始化了一次。

當(dāng)然,我可以在每一個(gè)繼承于Table的class里新增一句 _pk_cache = {},但是這樣的實(shí)現(xiàn)太丑了,而且一不注意就會(huì)漏掉導(dǎo)致出錯(cuò)。

所以我需要一個(gè)class initializer,在class被創(chuàng)建的時(shí)候,給它新增一個(gè)_pk_cache 。

在搞清楚了metaclass之后,解決方法特別簡(jiǎn)單:

class TableInitializer(type):
    def __new__(cls, name, bases, attrs):
        attrs["_pk_cache"] = {}
        return super(TableInitializer, cls).__new__(cls, name, bases, attrs)
        
class Table(object):
    __metaclass__ = TableInitializer

    ... #以下不變

完。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/37669.html

相關(guān)文章

  • [譯]理解pythonmetaclass

    摘要:但我并不是一個(gè)翻譯者并不會(huì)嚴(yán)格遵守每行每句的翻譯有時(shí)候我會(huì)將表述換個(gè)順序省略一些我認(rèn)為無(wú)關(guān)緊要的話,以便讀者更好理解。類也是對(duì)象在理解之前,我們先要掌握中的類是什么。這個(gè)對(duì)象類自身?yè)碛挟a(chǎn)生對(duì)象實(shí)例的能力。不過(guò)這樣做是為了保持向后兼容性。 前言 這篇博客是我在stackoverflow上看了一個(gè)提問(wèn)回復(fù)后寫(xiě)的,例子基本用的都是e-satis本人的例子,語(yǔ)言組織也基本按照翻譯來(lái)。 但我并不...

    liuchengxu 評(píng)論0 收藏0
  • How does it work - with_metaclass

    摘要:先簡(jiǎn)單介紹下中的元類。元類就是創(chuàng)建類的類,對(duì)于元類來(lái)說(shuō),類是它的實(shí)例,將返回。中的所有類,都是的實(shí)例,換句話說(shuō),是元類的基類。 我在看源代碼的時(shí)候,經(jīng)常蹦出這一句:How does it work!竟然有這種操作?本系列文章,試圖剖析代碼中發(fā)生的魔法。順便作為自己的閱讀筆記,以作提高。 先簡(jiǎn)單介紹下Python中的元類(metaclass)。元類就是創(chuàng)建類的類,對(duì)于元類來(lái)說(shuō),類是它的實(shí)...

    testbird 評(píng)論0 收藏0
  • Python -- 元類metaclass詳解

    摘要:原鏈接中的元類是什么類也是對(duì)象在理解元類之前,需要掌握中類概念。事實(shí)上,是中用于創(chuàng)建所有類的元類。類本身是元類的對(duì)象在中,除了,一切皆對(duì)象,一切都是類或者元類的對(duì)象。事實(shí)上是自己的元類, 學(xué)習(xí)契機(jī) 項(xiàng)目中使用Elasticsearch(ES)存儲(chǔ)海量業(yè)務(wù)數(shù)據(jù),基于ES向外提供的API進(jìn)一層封裝,按需處理原始數(shù)據(jù)提供更精確、更多樣化的結(jié)果。在研究這一層的代碼時(shí)接觸到@six.add_me...

    tracy 評(píng)論0 收藏0
  • python 類和元類(metaclass)的理解和簡(jiǎn)單運(yùn)用

    摘要:什么是元類剛才說(shuō)了,元類就是創(chuàng)建類的類。類上面的屬性,相信愿意了解元類細(xì)節(jié)的盆友,都肯定見(jiàn)過(guò)這個(gè)東西,而且為之好奇。使用了這個(gè)魔法方法就意味著就會(huì)用指定的元類來(lái)創(chuàng)建類了。深刻理解中的元類 (一) python中的類 今天看到一篇好文,然后結(jié)合自己的情況總結(jié)一波。這里討論的python類,都基于python2.7x以及繼承于object的新式類進(jìn)行討論。 首先在python中,所有東西都...

    zhangqh 評(píng)論0 收藏0
  • Python: 陌生的 metaclass

    摘要:但一般情況下,我們使用類作為元類。那么,元類到底有什么用呢要你何用元類的主要目的是為了控制類的創(chuàng)建行為。當(dāng)然,有很多種做法,這里展示用元類的做法。當(dāng)你創(chuàng)建類時(shí),解釋器會(huì)調(diào)用元類來(lái)生成它,定義一個(gè)繼承自的普通類意味著調(diào)用來(lái)創(chuàng)建它。 元類 Python 中的元類(metaclass)是一個(gè)深度魔法,平時(shí)我們可能比較少接觸到元類,本文將通過(guò)一些簡(jiǎn)單的例子來(lái)理解這個(gè)魔法。 類也是對(duì)象 在 Py...

    miya 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<