python 反射和動態載入 Python的反射

2021-10-11 12:39:23 字數 2885 閱讀 1649

什麼是反射

反射是乙個很重要的概念,它可以把字串對映到例項的變數或者例項的方法然後可以去執行呼叫、修改等操作。它有四個重要的方法:

getattr 獲取指定字串名稱的物件屬性

setattr 為物件設定乙個物件

hasattr 判斷物件是否有對應的物件(字串)

delattr 刪除指定屬性

attr是屬性英文的前幾個字母,屬性指的是類中類變數、例項變數和方法。但是要注意不能是私有的,如果你的變數是以「_」開頭,那將無法獲取。

反射常常用在動態載入模組的場景中。

#!/usr/bin/env python#-*- coding: utf-8 -*-#author: rex.cheny#e-mail: [email protected]

classtestobj(object):def __init__(self, name, age):

self.name=name

self.age=agedefdisplayname(self):print("displayname方法執行,列印姓名:", self.name)defaaa(self):print("i am aaa.")defmain():

to= testobj("tom", 23)#檢視 to 例項裡面是否有 name 這個屬性

if hasattr(to, "name"):print("例項 to 中有 name 屬性。")print(getattr(to, "name"))else:print("例項 to 中沒有 name 屬性。")if hasattr(to, "displayname"):print("例項 to 中有 displayname 屬性。")

getattr(to,"displayname")()else:print("例項 to 中沒有 displayname 屬性。")if hasattr(to, "aaa"):print("例項 to 中有 aaa 屬性。")

getattr(to,"aaa")()else:print("例項 to 中沒有 aaa 屬性,將會設定。")

setattr(to,"aaa", aaa) #引數:例項、方法名稱、具體方法 相當於 to.aaa = aaa 第乙個aaa是函式在例項中的名稱, 第二個aaa是把哪個函式放進去,兩者只是恰好這裡名稱一樣

#to.aaa(to) # 這裡一定要主動傳遞乙個例項進去,因為它不會自動裝配self

getattr(to, "aaa")(to)if __name__ == '__main__':

main()

aaa是動態裝載到例項裡面去的。

可能有些人還沒明白反射,反射就是把字串反射成記憶體物件,看下面的例子

#!/usr/bin/env python#-*- coding: utf-8 -*-#author: rex.cheny#e-mail: [email protected]

classtestobj(object):def __init__(self, name):

self.name=namedefdisplayname(self):print(self.name)defmain():

to= testobj(name="tom")

cmd= input("輸入:")ifhasattr(to, cmd):pass

else:

setattr(to, cmd, displayname)

func=getattr(to, cmd)

func(to)if __name__ == '__main__':

main()

根據使用者輸入來呼叫函式(這個函式肯定要提前的真實存在)。我這裡無論我輸入什麼都可以執行上面的displayname方法。現在應該明白字串對映到方法了吧。

反射使用

通過字串匯入模組

#!/usr/bin/env python#-*- coding: utf-8 -*-#author: rex.cheny#e-mail: [email protected]

temp= "re"model= __import__(temp)defmain():

txt= "hj123uo"pattern= model.compile(r"[0-9]+")print(model.search(pattern, txt).group())if __name__ == '__main__':

main()

以字串的形式使用模組的方法

#!/usr/bin/env python#-*- coding: utf-8 -*-#author: rex.cheny#e-mail: [email protected]

temp= "re" #要引入的模組

func = "compile" #要使用的方法

model = __import__(temp) #匯入模組

function = getattr(model, func) #找到模組中的屬性

defmain():

txt= "hj123uo"pattern= function(r"[0-9]+") #這裡執行funcation()就等於執行re.compile()函式

print(model.search(pattern, txt).group())if __name__ == '__main__':

main()

反射到底有什麼用?

上面使用re.compile()函式的整個過程看起來很麻煩,但是你要知道這就等於實現了動態載入和執行所需要的模組或方法而不需要全部寫入到py檔案中,當然具體需要執行的方法你也要提前實現。典型的使用場景就是web的url路由。目前所有的web框架的url路由基本都是這個原理。

使用者輸入不同的url如何載入不同的py檔案以及呼叫裡面的方法呢?你想一想django裡面,它並不是這樣的,它依然需要你設定url以及該url對應的py檔案,為什麼?因為這樣除錯方便,當然你能力足夠也可以給它改寫成反射的機制。

反射2 動態載入類

動態載入 和靜態載入的區別 class.forname 類的全稱 編譯時刻載入類是靜態載入類,執行時刻載入類是動態載入類。package dog public class animal if cat equals args 0 package dog public class dog 很顯然以上第一...

python非同步載入和動態 Vue動態載入非同步元件

背景 目前我們專案都是按元件劃分的,然後各個元件之間封裝成產品。目前都是採用iframe直接巢狀頁面。專案中我們還是會碰到一些通用的元件跟業務之間有通訊,這種情況下iframe並不是最好的選擇,iframe存在跨域的問題,當然是postmessage還是可以通訊的,但也並非是最好的。目前有這麼乙個場...

程式集載入和反射

元資料表是用一系列字段表,方法表,型別定義表組成的。可以利用system.reflection命名空間中包含的型別,可以寫 來反射這些元資料表。具體的反射機制我是這樣理解的 首先應該清楚的了解到,system.reflection命名空間中的型別為程式集或模組中包含的換資料表提供了乙個物件模型 通過...