反射機(jī)制是面向?qū)ο缶幊陶Z(yǔ)言中比較重要的功能,可以動(dòng)態(tài)獲取對(duì)象信息以及動(dòng)態(tài)調(diào)用對(duì)象,Python作為一門動(dòng)態(tài)編程語(yǔ)言,當(dāng)然也有反射機(jī)制,本文介紹Python反射函數(shù)使用方法。
創(chuàng)新互聯(lián)建站專業(yè)為企業(yè)提供泰寧網(wǎng)站建設(shè)、泰寧做網(wǎng)站、泰寧網(wǎng)站設(shè)計(jì)、泰寧網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)與制作、泰寧企業(yè)網(wǎng)站模板建站服務(wù),十年泰寧做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。
在程序運(yùn)行時(shí)可以獲取對(duì)象類型定義信息,例如,Python中的type(obj)將返回obj對(duì)象的類型,這種獲取對(duì)象的type、attribute或者method的能力稱為反射。通過(guò)反射機(jī)制,可以用來(lái)檢查對(duì)象里的某個(gè)方法,或某個(gè)變量是否存在。也就是可以 通過(guò)字符串映射對(duì)象的方法或者屬性 。
Python反射常用的內(nèi)置函數(shù)
先創(chuàng)建一個(gè)類:
利用反射的能力,我們可以通過(guò)屬性字典 __dict__ 來(lái)訪問(wèn)對(duì)象的屬性:
執(zhí)行輸出:
接下來(lái)測(cè)試一下其他反射函數(shù):
Out:
Out:
Out:
Out:
Out:
Out:
下面介紹兩種Python反射的應(yīng)用場(chǎng)景。
從前面舉的例子中,我們了解到可以通過(guò) 字符串 來(lái)獲取對(duì)象的屬性( getattr() ),這是非常有用的一個(gè)功能。比如,一個(gè)類中有很多方法,它們提供不同的服務(wù),通過(guò)輸入的參數(shù)來(lái)判斷執(zhí)行某個(gè)方法,一般的使用如下寫法:
如果函數(shù)比較少這樣寫沒(méi)有太大問(wèn)題,如果有很多,這樣寫就比較復(fù)雜了,需要寫大量else語(yǔ)句,可以使用反射機(jī)制來(lái)寫:
這樣是不是簡(jiǎn)潔了很多,上面的例子中,通過(guò)反射,將字符串變成了函數(shù),實(shí)現(xiàn)了對(duì)對(duì)象方法的動(dòng)態(tài)調(diào)用。
可以通過(guò)setattr()方法進(jìn)行動(dòng)態(tài)屬性設(shè)置,在使用scapy庫(kù)構(gòu)造報(bào)文時(shí),我們需要設(shè)置某些報(bào)文字段,然而網(wǎng)絡(luò)協(xié)議的報(bào)文字段很多,在需要設(shè)置大量字段時(shí),一個(gè)一個(gè)的賦值就很麻煩:
可以使用setattr()方法來(lái)賦值:
--THE END--
動(dòng)態(tài)語(yǔ)言里面的eval就是干這個(gè)用的
type1="int"
type2="str"
a=eval(type1+"(2222)") 這里a就是int型的2222 相當(dāng)于執(zhí)行a=eval("int(2222)")
b=eval(type2+("2222")) 這里b就是string型的"2222" 相當(dāng)于執(zhí)行b=eval("str(2222)")
另外Python偏函數(shù)特性也比較像這個(gè),你可以搜索下看看。
這個(gè)也是python彪悍的特性.
自省就是面向?qū)ο蟮恼Z(yǔ)言所寫的程序在運(yùn)行時(shí),所能知道對(duì)象的類型.簡(jiǎn)單一句就是運(yùn)行時(shí)能夠獲得對(duì)象的類型.比如type(),dir(),getattr(),hasattr(),isinstance().
反射機(jī)制就是在運(yùn)行時(shí),動(dòng)態(tài)的確定對(duì)象的類型,并可以通過(guò)字符串調(diào)用對(duì)象屬性、方法、導(dǎo)入模塊,是一種基于字符串的事件驅(qū)動(dòng)
通過(guò)源碼注釋我們知道,它返回對(duì)象是否具有指定名稱的屬性。而且它是通過(guò)調(diào)用getattr并捕獲AttributeError異常來(lái)判斷的。就像上面的屬性調(diào)用,我們就可以使用hasattr(a, "test")來(lái)判斷,通過(guò)源碼注釋我們也可以思考一下,eval這種是不是也可以實(shí)現(xiàn)這種方法呢?
但是這種方式是有缺陷的,因?yàn)閠est輸出了兩次,因?yàn)槲覀冋{(diào)用了兩次test(),這跟我們想要的效果不一樣。如果用hasattr呢,這個(gè)函數(shù)就不會(huì)在判斷的時(shí)候調(diào)用一次了。
有了判斷屬性是否存在的函數(shù),那么就得有獲取屬性的函數(shù)了.
從源碼注釋我們就能知道獲取object對(duì)象的名為name的屬性,想到與object.name,如果提供了default參數(shù),那么當(dāng)屬性不存在的時(shí)候,就會(huì)返回默認(rèn)值。同樣是上面的例子:
從例子中我們可以看出,hasattr并沒(méi)有調(diào)用test函數(shù),而且getattr獲取到的是函數(shù)對(duì)象,也沒(méi)有調(diào)用它,通過(guò)我們主動(dòng)執(zhí)行func()才執(zhí)行了a.test()函數(shù),這樣相比于exec和eval就靈活了許多。
判斷和獲取屬性有了,那么設(shè)置屬性也是需要的.