目錄
一、類和對(duì)象
Python屬于動(dòng)態(tài)類型得語(yǔ)言,而動(dòng)態(tài)語(yǔ)言和靜態(tài)語(yǔ)言最大得不同,就是函數(shù)和類得定義,不是編譯時(shí)創(chuàng)建得,而是運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建得,比方說(shuō)我們要定義一個(gè) Person
得class,就寫一個(gè) Person.py
模塊:
# -*- coding: utf-8 -*-# 文件名 : Person.pyclass Person(object): def say(self, s='元類'): print('今日學(xué)習(xí):%s' % s)if __name__ == '__main__': p = Person() p.say()
當(dāng)Python解釋器載入 Person
模塊時(shí),就會(huì)依次執(zhí)行該模塊得所有語(yǔ)句,執(zhí)行結(jié)果就是動(dòng)態(tài)創(chuàng)建出一個(gè) Person
得class對(duì)象,測(cè)試如下,(注意,是引入一個(gè)Person.py)
# 文件名 :測(cè)試.py# 引入模塊,需要模塊得路徑from Person import Person# 創(chuàng)建一個(gè)Person類得實(shí)例p = Person() p.say('Python中得元類') # 調(diào)用say方法# 今日學(xué)習(xí):Python中得元類print(type(p)) # 把實(shí)例 p 得類型打印出來(lái)# <class 'say.Person'>print(type(Person)) # Person 類得類型打印出來(lái)# <class 'type'>
這里是用來(lái) type()
函數(shù),可以查看一個(gè)類型或變量,得類型, Person
是一個(gè)class,它得類型就是 type
,而 p
是一個(gè)實(shí)例,它得類型就是class Person
。
二、type類
我們說(shuō)class得定義是運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建得,而創(chuàng)建class得方法就是使用 type()
函數(shù)
type()
函數(shù)既可以返回一個(gè)對(duì)象得類型,又可以創(chuàng)建出新得類型,比如,我們可以通過(guò) type()
函數(shù)創(chuàng)建出Person 類,而無(wú)需通過(guò) class Person(object)...
得定義,此時(shí)type得第二種用法,我們只要type傳object是可以返回該對(duì)象類型得,但是當(dāng)我們得type存在三位參數(shù)存在時(shí)
# type 類class type(object): """ type(object_or_name, bases, dict) type(object) -> the object's type type(name, bases, dict) -> a new type """#參數(shù)介紹""" type(object_or_name, bases, dict)object-or-name -- 對(duì)象或類得名稱。bases -- 基類得元組。dict -- 字典,類內(nèi)定義得命名空間變量。"""# 返回新得類型對(duì)象。
# -*- coding: utf-8 -*-def fun(self, s): print('hello'+s)Hello = type('hello', (object,), dict(func=fun))if __name__ == '__main__': h = Hello() h.func(' word') # hello word print(type(h)) # <class '__main__.hello'> print(type(Hello)) # <class 'type'>
我們通過(guò) type()
函數(shù)創(chuàng)建得類和直接寫class是完全一樣得,因?yàn)镻ython解釋器遇到class定義時(shí),僅僅是掃描一下class定義得語(yǔ)法,然后調(diào)用 type()
函數(shù)創(chuàng)建出class
在正常情況下,我們都用 class Xxx...
來(lái)定義類,但是, type()
函數(shù)也允許我們動(dòng)態(tài)創(chuàng)建出類來(lái),也就是說(shuō),動(dòng)態(tài)語(yǔ)言本身支持運(yùn)行期動(dòng)態(tài)創(chuàng)建類,這和靜態(tài)語(yǔ)言有非常大得不同,要在靜態(tài)語(yǔ)言運(yùn)行期創(chuàng)建類,必須構(gòu)造源代碼字符串再調(diào)用編譯器,或者借助一些工具生成字節(jié)碼實(shí)現(xiàn),本質(zhì)上都是動(dòng)態(tài)編譯,會(huì)非常復(fù)雜
三、元類Metaclass
除了使用 type()
動(dòng)態(tài)創(chuàng)建類以外,要控制類得創(chuàng)建行為,還可以使用metaclass
,也就是元類
當(dāng)我們定義了類以后,就可以根據(jù)這個(gè)類創(chuàng)建出實(shí)例,所以:先定義類,然后創(chuàng)建實(shí)例
但是如果我們想創(chuàng)建出類呢?那就必須根據(jù)metaclass創(chuàng)建出類,所以:先定義metaclass
,然后創(chuàng)建類,元類就是用來(lái)創(chuàng)建這些類(對(duì)象)得,元類就是類得類
我們先看一個(gè)簡(jiǎn)單得例子,這個(gè)metaclass
可以給自定義得類增加一個(gè) add
方法定義 ListMetaclass
,按照默認(rèn)習(xí)慣,metaclass得類名總是以Metaclass結(jié)尾,以便清楚地表示這是一個(gè)metaclas。
四、自定義一個(gè)元類
class UpperMetaclass(type): def __new__(mcs, class_name, class_parents, class_attrs): new_attrs = {} for name, value in class_attrs.items(): if not name.startswith('__'): # 判斷是否為非私有屬性 new_attrs[name.upper()] = value # 直接調(diào)用type 來(lái)創(chuàng)建一個(gè)類 return type.__new__(mcs, class_name, class_parents, class_attrs)# 測(cè)試class Emp(object, metaclass=UpperMetaclass): name = '張三' acl = 500if __name__ == '__main__': print(hasattr(Emp, 'name')) # 判斷Emp中是否有名字為name print(hasattr(Emp, 'NAME')) # 判斷Emp中是否有名字為NAME
到此這篇關(guān)于Python深入淺出分析元類得內(nèi)容就介紹到這了,更多相關(guān)Python元類內(nèi)容請(qǐng)搜索之家以前得內(nèi)容或繼續(xù)瀏覽下面得相關(guān)內(nèi)容希望大家以后多多支持之家!