在python的內(nèi)置函數(shù)中,有這么幾個的內(nèi)置函數(shù) 吮铭,分別是:getattr(),setattr(),delattr(),hasattr(),
這些內(nèi)置函數(shù)主要應(yīng)用在反射臣嚣。我們在學(xué)習(xí)函數(shù)的模塊的時候,知道在應(yīng)用第三方模塊的時候剥哑,首先是要導(dǎo)入才可以使用的硅则,導(dǎo)入使用的是import,那么我們今天使用另外的一種導(dǎo)入方式株婴,也就是__import__
怎虫,通過它來實現(xiàn)模塊中函數(shù)的應(yīng)用,再來引出反射的實際應(yīng)用困介。我們創(chuàng)建模塊day2,day3大审,在day2模塊中編寫login和logout的函數(shù),見代碼:
def login():
print('我是login函數(shù)')
def logout():
print('我是logout函數(shù)')
現(xiàn)在我們實現(xiàn)在day3中調(diào)用login和logout的函數(shù)座哩,我們不使用import的方式徒扶,我們通過__import__
的方式,見實現(xiàn)的過程:
index=__import__('day2')
#調(diào)用day2模塊中的login函數(shù)
index.login()
#調(diào)用day3中l(wèi)ogout的函數(shù)
index.logout()
見執(zhí)行后的輸出內(nèi)容:
我是login函數(shù)
我是logout函數(shù)
依據(jù)執(zhí)行結(jié)果根穷,我們可以看到姜骡,實現(xiàn)了調(diào)用login和調(diào)用logout函數(shù)的效果,那么在這里屿良,是怎么實現(xiàn)的了圈澈?大概可以總結(jié)為:
1、通過__import__
的形式導(dǎo)入模塊尘惧,并賦值給字符串
2士败、通過字符串的形式去模塊中尋找指定的函數(shù),并執(zhí)行
下面我們來通過getattr的方式褥伴,來實現(xiàn)如上的實現(xiàn)過程谅将,getattr簡單的可以理解為:“依據(jù)字符串的形式去模塊中尋找指定的目標(biāo)對象(模塊中的函數(shù),或者類中的方法)”重慢,見實現(xiàn)的代碼為:
import day2
f=getattr(day2,'login')
f()
見執(zhí)行的結(jié)果:
我是login函數(shù)
通過getattr()的方式更加簡單饥臂,它的第一個參數(shù)是對象模塊,第二個參數(shù)是指定的模塊似踱,最后一個是默認(rèn)參數(shù)None隅熙,見getattr()方法的源碼:
def getattr(object, name, default=None): # known special case of getattr
"""
getattr(object, name[, default]) -> value
Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
When a default argument is given, it is returned when the attribute doesn't
exist; without it, an exception is raised in that case.
"""
pass
如上的形式,可以總結(jié)為:通過字符串的形式核芽,來尋找模塊中的函數(shù)并執(zhí)行函數(shù)囚戚。粗暴的實現(xiàn)為:
import day2
inp_func=raw_input(u'請輸入要執(zhí)行的函數(shù):\n')
target_func=getattr(day2,inp_func)
print('執(zhí)行目標(biāo)函數(shù):', target_func())
該代碼其實和最初上面的代碼實現(xiàn)思想是一致的,就是使用getattr()方法來獲取模塊中的函數(shù)并執(zhí)行函數(shù)轧简。
其實在開始的時候驰坊,已經(jīng)說了,除了getattr()內(nèi)置函數(shù)外哮独,還有其他的幾個內(nèi)置函數(shù)拳芙,具體為:
根據(jù)字符串的形式去某個模塊中尋找東西--->getattr()
根據(jù)字符串的形式去某個模塊中判斷東西是否存在--->hasattr()
根據(jù)字符串的形式去某個模塊中設(shè)置東西---->setattr()
根據(jù)字符串的形式去某個模塊中刪除東西---->delattr()
如下我們通過一個案例察藐,來引入反射的基本使用。
commons模塊的代碼為:
def index():
print('index')
def login():
print('login')
def logout():
print('logout')
創(chuàng)建一個新的模塊舟扎,導(dǎo)入commons模塊分飞,來調(diào)用該模塊中編寫的方法,見實現(xiàn)的代碼:
import commons
url=raw_input('請模擬瀏覽器輸入路由:\n')
if url.endswith('index'):
commons.index()
elif url.endswith('login'):
commons.login()
elif url.endswith('logout'):
commons.logout()
else:
print('Sorry,尋找路由失敗')
下面我們通過反射的方式來進(jìn)行修改睹限,見修改后的代碼:
import commons
url=raw_input('請模擬瀏覽器輸入路由:\n')
per=url.split('/')[-1]
if hasattr(commons,per):
target_function=getattr(commons,per)
target_function()
else:
print('Not Found 404 Page')
如上的代碼修改了很多的譬猫,但是還是有一個缺點的,就是我們需要導(dǎo)入模塊羡疗,但是在實際的工作中删窒,我們基本不清楚路由是來自哪個模塊的,需要對如上的代碼進(jìn)行二次重構(gòu)顺囊,重構(gòu)后的代碼為:
url=raw_input('請模擬瀏覽器輸入路由:\n')
target_models,target_function=url.split('/')
m=__import__(target_models)
if hasattr(m,target_function):
target_function=getattr(m,target_function)
target_function()
else:
print('Not Found 404 Page')