python中的元类_python中的元类
類也是對(duì)象,但是類有創(chuàng)建對(duì)象的能力
動(dòng)態(tài)創(chuàng)建一個(gè)類:
classmonkey():defbanana(self):print 'banana!'
defapple(self):print 'i want apple!'monkey_child= type('monkey_child', (monkey,), {'apple': apple})
hasattr(monkey,'apple')
false
hasattr(monkey_child,'apple')
true
type的語(yǔ)法:type(類名,父類的元組(針對(duì)繼承的情況,可以為空),包含屬性的字典(名稱和值))
創(chuàng)建類的就是元類,type是所有類的元類,類屬性__class__可以看到元類是什么
>>> a=1
>>>type(a)
>>> type(a.__class__)
創(chuàng)建一個(gè)類的過(guò)程:搜索__metaclass__是否有指定,否則搜索父類中的__metaclass__,最終應(yīng)該找到type或是type的子類
由于python中鴨子類型的概念,__metaclass__實(shí)際上不一定是一個(gè)類,也可以是一個(gè)函數(shù)
defupper_attr(future_class_name, future_class_parents, future_class_attr):
attrs= ((name, value) for name, value in future_class_attr.items() if not name.startswith('__'))
uppercase_attr= dict((name.upper(), value) for name, value inattrs)returntype(future_class_name, future_class_parents, uppercase_attr)classFoo(object):__metaclass__ =upper_attr
bar= 'aip'
printFoo.BAR>>>'aip'
在Python3中我們?cè)诙x類時(shí)通過(guò)傳入metaclass的參數(shù)來(lái)設(shè)定,如上代碼就應(yīng)該寫成class Foo(metaclass=upper_attr)。
metaclass可以是一個(gè)類
classUpperAttrMetaclass(type):def __new__(cls, name, bases, dct):
attrs= ((name, value) for name, value in dct.items() if not name.startswith('__')
uppercase_attr= dict((name.upper(), value) for name, value inattrs)return type.__new__(cls, name, bases, uppercase_attr)
__new__在__init__之前被調(diào)用,用于創(chuàng)建和返回對(duì)象,由__new__是一個(gè)類方法,我們需要傳入實(shí)例對(duì)象cls。
為了表明繼承關(guān)系,以上代碼可以寫成
classUpperAttrMetaclass(type):def __new__(cls, name, bases, dct):
attrs= ((name, value) for name, value in dct.items() if not name.startswith('__'))
uppercase_attr= dict((name.upper(), value) for name, value inattrs)return super(UpperAttrMetaclass, cls).__new__(cls, name, bases, uppercase_attr)
為什么要用metaclass類而不是函數(shù)?
由于__metaclass__可以接受任何可調(diào)用的對(duì)象,那為何還要使用類呢,因?yàn)楹茱@然使用類會(huì)更加復(fù)雜啊?這里有好幾個(gè)原因:
1) 意圖會(huì)更加清晰。當(dāng)你讀到UpperAttrMetaclass(type)時(shí),你知道接下來(lái)要發(fā)生什么。
2) 你可以使用OOP編程。元類可以從元類中繼承而來(lái),改寫父類的方法。元類甚至還可以使用元類。
3) 你可以把代碼組織的更好。當(dāng)你使用元類的時(shí)候肯定不會(huì)是像我上面舉的這種簡(jiǎn)單場(chǎng)景,通常都是針對(duì)比較復(fù)雜的問(wèn)題。將多個(gè)方法歸總到一個(gè)類中會(huì)很有幫助,也會(huì)使得代碼更容易閱讀。
4) 你可以使用__new__, __init__以及__call__這樣的特殊方法。它們能幫你處理不同的任務(wù)。就算通常你可以把所有的東西都在__new__里處理掉,有些人還是覺得用__init__更舒服些。
根據(jù)http://python3-cookbook.readthedocs.io/zh_CN/latest/c08/p07_calling_method_on_parent_class.html 可以知道,我們應(yīng)該在繼承并改寫的代碼中盡量使用super訪問(wèn)父類,而不是直接訪問(wèn)父類。
classUpperAttrMetaclass(type):def __new__(cls, name, bases, dct):
attrs= ((name, value) for name, value in dct.items() if not name.startswith('__'))
uppercase_attr= dict((name.upper(), value) for name, value inattrs)return super(UpperAttrMetaclass, cls).__new__(cls, name, bases, uppercase_attr)
參考:http://blog.jobbole.com/21351/
其中有一個(gè)Django的ORM的例子,學(xué)習(xí)之
總結(jié)
以上是生活随笔為你收集整理的python中的元类_python中的元类的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python爬取晋江_[Arcpy] 爬
- 下一篇: python gui框架_Python的