面向?qū)ο蟾呒?jí)--反射、內(nèi)置方法和元類

1.反射

1.1什么是反射

python是一門動(dòng)態(tài)語言,而反射機(jī)制被視為動(dòng)態(tài)語言的關(guān)鍵!

創(chuàng)新互聯(lián)建站于2013年開始,先為達(dá)孜等服務(wù)建站,達(dá)孜等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為達(dá)孜企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。

反射機(jī)制指的是:在程序的運(yùn)行過程中,動(dòng)態(tài)的獲取程序的信息和對(duì)象的功能!

‘動(dòng)態(tài)’:指一開始不知道程序的信息和對(duì)象的功能,只有等到運(yùn)行到那的時(shí)候才會(huì)動(dòng)態(tài)獲取!!!

比如:x=18
在程序運(yùn)行的時(shí)候,python才會(huì)通過反射機(jī)制動(dòng)態(tài)的獲取到這個(gè)值是整型,并不需要一開始定義的時(shí)候,就規(guī)定這個(gè)18位整型!

1.2為什么要用反射機(jī)制

當(dāng)我們獲取一個(gè)對(duì)象時(shí),很多場(chǎng)景下,我們是并不知道這個(gè)對(duì)象里面是有什么屬性和方法的,我們需要通過反射機(jī)制,動(dòng)態(tài)的獲取到該對(duì)象的屬性和方法!!

案例:當(dāng)我們?cè)诮邮沼脩糨斎胫噶畹臅r(shí)候,我們接收的是一個(gè)用戶輸入的字符串類型的指令,我們需要通過反射機(jī)制判斷,這個(gè)字符串是不是該對(duì)象的功能,如果是調(diào)用該功能,如果不是返回提示信息!

案例代碼化:

class Func:
    def put(self):
        print('正在執(zhí)行上傳功能')

    def get(self):
        print('正在執(zhí)行下載功能')

    # 該函數(shù)是用來接收用戶的操作指令,并判斷該對(duì)象是否有該功能,有則執(zhí)行,沒有則提示沒有該功能
    def action(self):
        action = input('請(qǐng)輸入操作指令:')
        if hasattr(self,action):
            getattr(self,action)()
        else:
            print('沒有該功能')
obj = Func()
obj.action()

1.3如何實(shí)現(xiàn)反射機(jī)制

其實(shí)就是四個(gè)內(nèi)置函數(shù)的使用!

class People:
    def __init__(self,name):
        self.name = name
    def say(self):
        pass

obj = People('zhang')

# 1.可以通過dir方法獲取obj對(duì)象有哪些屬性
print(dir(obj)) # 格式是一個(gè)列表套字符串的形式

# 2.通過字符串反射到真正的屬性上,從而得到屬性,操作屬性
# 四個(gè)內(nèi)置函數(shù)的使用
print(hasattr(obj,'name'))  # hasattr()判斷obj這個(gè)對(duì)象有沒有name這個(gè)屬性,name是字符串格式
print(getattr(obj,'name'))  # 等同于obj.name
setattr(obj,'name','yang') # 等同于obj.name='yang'
delattr(obj,'name')  # 等同于 del obj.name
print(obj.__dict__)  # 結(jié)果為{}
# 上述四個(gè)方法也可以括號(hào)里放個(gè)類,判讀類是否有該函數(shù)
res = getattr(People,'say')  # 等同于People.say
print(res)

2.內(nèi)置方法

2.1什么是內(nèi)置方法

定義在類的內(nèi)部,以__開頭__結(jié)尾的方法

特點(diǎn)是在滿足某種情況下自動(dòng)觸發(fā)該方法!!!!

2.2為毛要用內(nèi)置方法

為了自定義定制我們的類or對(duì)象

2.3如何使用內(nèi)置方法

2.3.1 __str__方法

class Func:
    def put(self):
        print('正在執(zhí)行上傳功能')
    def __str__(self):
        return 'w1e' # 打印對(duì)象是返回的值,必須位字符串類型
obj = Func()
print(obj)  # 等同于print(obj.__str__())
# 不定義__str__方法,印出來為<__main__.Func object at 0x00000149DE206FA0>
# 定義__str__方法,可以在__str__內(nèi)部函數(shù)指定返回的東西,return后面必須是字符串類型

2.3.2 __del__方法

該方法是在清理對(duì)象之前觸發(fā),會(huì)先執(zhí)行該方法

class Func:
    def put(self):
        print('正在執(zhí)行上傳功能')
    def __del__(self):
        print('run...')
        # 在del內(nèi)部更多的是進(jìn)行清理該對(duì)象占用系統(tǒng)的資源,對(duì)象清理了需要發(fā)起系統(tǒng)調(diào)用,清理對(duì)象占據(jù)的系統(tǒng)資源!
obj = Func()
del obj # 清理對(duì)象了,清理完之后會(huì)直接調(diào)用__del__方法,然后在執(zhí)行下面的代碼;如果不手動(dòng)清理,在執(zhí)行代碼全部運(yùn)行完之后,程序也會(huì)清理,打印run
print('====')

2.3.3 __call__方法

如果想要讓一個(gè)對(duì)象可以加括號(hào)調(diào)用,需要在該對(duì)象的類中添加一個(gè)__call__方法

class Person(object):
    def __init__(self,name):
        self.name=name

    def __call__(self, *args, **kwargs):
        print(args,kwargs) #a()里傳入的參數(shù)
        return 123  # __call__的返回值就是a()的返回值

a = Person('zhang')
res = a(1,2,3,a=4,b=5) # 如果想要讓對(duì)象a可以加括號(hào)調(diào)用,就必須在該對(duì)象的類中定義__call__方法,不添加則報(bào)錯(cuò)
print(res)

同樣,如果想要類可以加括號(hào)調(diào)用,需要在該類的元類里添加一個(gè)__call__方法

調(diào)用__call__方法完成了三件事:
1.調(diào)用該類中的__new__方法造出一個(gè)空對(duì)象
2.調(diào)用該類中的__init__方法造出一個(gè)初始化對(duì)象(給上面的空對(duì)象添加屬性,穿衣服)
3.返回初始化好的對(duì)象

2.4 總結(jié)

了解:這些內(nèi)置方法__str__等又稱魔法方法!

# __init__:類實(shí)例化會(huì)觸發(fā)
# __str__:打印對(duì)象會(huì)觸發(fā)
# __call__:對(duì)象()觸發(fā),類也是對(duì)象  類(),類的實(shí)例化過程調(diào)用元類的__call__
# __new__:在類實(shí)例化會(huì)觸發(fā),它比__init__早(造出裸體的人,__init__穿衣服)
# __del__:del 對(duì)象,對(duì)象回收的時(shí)候觸發(fā)
# __setattr__,__getattr__:(.攔截方法),當(dāng)對(duì)象.屬性--》賦值會(huì)調(diào)用setattr,如果是取值會(huì)調(diào)用getattr
# __getitem__,__setitem__:([]攔截)
# __enter__和__exit__ 上下文管理器

上下文管理器應(yīng)用:

class Person:
    def __enter__(self):
        print("我在with管理的時(shí)候,會(huì)觸發(fā)")
        print('進(jìn)入with語句塊時(shí)執(zhí)行此方法,此方法如果有返回值會(huì)賦值給as聲明的變量')
        return 'oo'

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('退出with代碼塊時(shí)執(zhí)行此方法')
        print('1', exc_type)
        print('2', exc_val)
        print('3', exc_tb)


with Person() as p:   # 這句話執(zhí)行,會(huì)觸發(fā)類的__enter__
    print(p)

小練習(xí):類中可以通過對(duì)象.屬性的方式獲取值和設(shè)置值,但是不可以通過對(duì)象['鍵']=值設(shè)置值和獲取值,思考如何可以實(shí)現(xiàn)呢?

class Person:
    def __init__(self,name):
        self.name = name

    def __setitem__(self, key, value): # 重寫類的__setitem__方法
        setattr(self,key,value) # 當(dāng)對(duì)象['鍵']=值觸發(fā)該方法,調(diào)用setattr是觸發(fā)self.key=value

    def __getitem__(self, item): # 同上
        return getattr(self,item)

p = Person('zy')
print(p.name)
p['name']=10
print(p['name'])

3.元類

3.1什么是元類

元類就是用來實(shí)例化產(chǎn)生類的類

關(guān)系:元類--->實(shí)例化--->類--->實(shí)例化--->對(duì)象(obj)

3.2如何查看內(nèi)置的元類

其實(shí),我們使用class定義的各種類和內(nèi)置的類都是由內(nèi)置的元類type幫我們實(shí)例化產(chǎn)生的

我們可以使用type()函數(shù)查看內(nèi)置的元類

例如:在python中int、dict內(nèi)置元類都繼承自object類,int和dict又都是type元類的對(duì)象

print(type(int))  # <class 'type'>
print(type(dict)) # <class 'type'>

那么type和object又是什么關(guān)系呢?我們來type一下object和type!

print(type(type))  #<class 'type'>
print(type(object)) #<class 'type'>

其實(shí):

1.object的元類其實(shí)是type類,object是由type類構(gòu)造出來的對(duì)象
2.type是自己的對(duì)象(指針指向了自己)
3.type類又繼承了object類

3.3class機(jī)制(class如何造出類的)

calss其實(shí)底層執(zhí)行了以下四個(gè)步驟,造出了類!

class Func:
    def put(self):
        print('正在執(zhí)行上傳功能')
    def __del__(self):
        print('run...')
# 1.得到類名
class_name = 'Func'

# 2.得到類的基類
class_bases = (object,)

# 3.執(zhí)行類體代碼拿到名稱空間!
class_dict = {}
class_body = """
def put(self):
    print('正在執(zhí)行上傳功能')
def __del__(self):
    print('run...')
"""
# exec第一個(gè)參數(shù)是類體代碼、第二個(gè)是類體代碼中的全局變量、第三的是一個(gè)空字典容器
exec (class_body,{},class_dict)
print(class_dict)

# 4.調(diào)用元類,得到People類
Func = type(class_name,class_bases,class_dict)
print(Func)

# Func類就是type元類實(shí)例化產(chǎn)生出來的對(duì)象!!!!

3.4如何自定義元類來控制類的產(chǎn)生

在3.3中,我們是使用type元類控制Func類的產(chǎn)生。其實(shí),我們也可以自定義元類來控制類產(chǎn)生

class MyMeta(type):   # 只有繼承了type的類才是元類
    def __init__(self,x,y,z): # 注意調(diào)用MyMeta這個(gè)類其實(shí)傳入了四個(gè)參數(shù)分別是self、class_name,class_bases,class_dict
        print('run...')
        print(x) # x對(duì)應(yīng)class_name
        print(y) # y對(duì)應(yīng)class_bases
        print(z) # z對(duì)應(yīng)class_dict

class Func(metaclass=MyMeta):
    def put(self):
        print('正在執(zhí)行上傳功能')
    def __del__(self):
        print('run...')

# 在自定義類的時(shí)候,metaclass默認(rèn)等于type,我們可以通過指定metaclass=MyMeta來自定義元類
# 指定了metaclass=MyMeta,其實(shí)就執(zhí)行了第四步調(diào)用元類Func = MyMeta(class_name,class_bases,class_dict)
# 調(diào)用MyMeta(class_name,class_bases,class_dict)發(fā)生了三件事!
# 注意!!!調(diào)用它就等于調(diào)用了type的__call__方法!!!!
#     1.先造一個(gè)空對(duì)象---Func--這里其實(shí)先調(diào)用了MyMeta類里的__new__()方法
#     2.調(diào)用MyMeta這個(gè)類的__init__方法,完成初始化對(duì)象操作
#     3.返回初始化好的對(duì)象

"""
完成上述操作之后,我們就可以在自定義的MyMeta元類里面的init方法里面,規(guī)定一下類的產(chǎn)生必須滿足那些條件!
"""

3.5 元類下的屬性查找

首先,切記!!父類不是元類!!

對(duì)象.屬性查找是先從自己那找,再到類中,再到該類的父類中,最后到object類

類.屬性查找是先從該類的父類中找,再到父類的父類中找,再到object中找,最后還要到該類的元類中找

網(wǎng)頁標(biāo)題:面向?qū)ο蟾呒?jí)--反射、內(nèi)置方法和元類
文章出自:http://m.kartarina.com/article46/dsogceg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計(jì)公司移動(dòng)網(wǎng)站建設(shè)定制網(wǎng)站Google標(biāo)簽優(yōu)化品牌網(wǎng)站設(shè)計(jì)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都做網(wǎng)站
主站蜘蛛池模板: 国产成年无码AV片在线韩国| 波多野结衣AV无码| 亚洲AV永久无码精品水牛影视| 无码国内精品久久人妻麻豆按摩 | 亚洲AV无码AV男人的天堂不卡| 无码综合天天久久综合网| 国产AV无码专区亚洲精品| 亚洲一区无码中文字幕乱码| 久久伊人亚洲AV无码网站| 日韩中文无码有码免费视频| 亚洲精品午夜无码电影网| 日韩少妇无码喷潮系列一二三 | 日本无码WWW在线视频观看| 成人午夜亚洲精品无码网站| 亚洲av日韩av无码av| 内射人妻少妇无码一本一道 | 中文字幕精品三区无码亚洲| 亚洲一区无码精品色| 日韩成人无码影院| 91嫩草国产在线无码观看| 国产成人无码精品久久久性色| 亚洲AV无码专区在线观看成人| 国产AV无码专区亚汌A√| 国产99久久九九精品无码| 人妻少妇看A偷人无码精品| 欧美性生交xxxxx无码影院∵| 国产网红无码精品视频 | 人妻无码久久久久久久久久久| 人妻无码中文久久久久专区| 亚洲av无码一区二区乱子伦as| 国产成人无码精品一区不卡| 无码人妻精品一区二区三区久久久 | 无码人妻精品一区二区蜜桃百度| 无码丰满熟妇juliaann与黑人| 亚洲av中文无码乱人伦在线r▽| 一区二区三区无码视频免费福利| 亚洲免费无码在线| 成人无码A区在线观看视频| 国产丝袜无码一区二区三区视频| 日韩a级无码免费视频| 中文一国产一无码一日韩|