日期:2020年3月19日
作者:Commas
註釋:學習就是爲了忘記
如果您想了解更多有關Python的知識,那麼請點《我的Python淺談系列目錄》
一、反射是什麼?
反射
是一個非常重要的概念,它是一種字符串
與對象
的映射關係,利用字符串
去操作對象
,可以對操作的對象進行成員的查找、獲取、添加以及刪除
。通俗地說,反射是一種基於字符串的事件驅動
,使用字符串就可以獲取對象中的屬性或方法(方法的內存地址,加西文圓括號()與對應傳參,即可執行),也可以添加或刪除對象中的屬性或方法,是不是很神奇呢?那我們接着往下看吧。
二、反射的四大工具
所謂工欲善其事,必先利其器。我們先來了解一下python反射的四大工具,如下:
分類 | 內置函數(工具) | 說明 |
---|---|---|
判斷 |
hasattr(obj, name) | 判斷對象obj中是否有屬性name |
獲取 |
getattr(obj, name[, default]) | 獲取對象obj的屬性name,等價於obj.name。若default有值,則name不存在就調用obj.default,否則name不存在就拋出異常 |
新增 |
setattr(obj, name, value) | 給對象obj設置一個屬性name,並且爲其賦值value,等價於obj.name = value |
刪除 |
delattr(obj, name) | 刪除對象obj的name屬性,等價於del obj.name |
其中attr是attribute的縮寫,即屬性。
三、反射的對象有哪些?
可以使用反射的對象總共有4類,如下:
- 實例化對象
- 類(類也是一個對象,類對象)
- 本模塊(.py結尾文件)
- 其他模塊(.python結尾文件)
(1)實例化對象的反射實例
class Rectangle:
"""矩形類"""
def __init__(self, b, h):
self.b = b
self.h = h
def cal_area(self):
return self.b*self.h
def cal_perimeter(self):
return (self.b+self.h)*2
def main():
# 實例化對象
rect = Rectangle(4, 5)
# (1)直接調用對象方法
print("(1)直接調用對象方法")
print(rect.b)
print(rect.h)
print(rect.cal_area())
print(rect.cal_perimeter())
# (2)實例化對象的反射
print("(2)實例化對象的反射")
list_attr = ["b", "h", "cal_area", "cal_perimeter"]
for str_attr in list_attr:
if hasattr(rect, str_attr):
obj_attr = getattr(rect, str_attr)
if callable(obj_attr): # if hasattr(obj_attr, '__call__'): #判斷是否可調用,即是否爲方法
# 反射屬性(對象方法)的地址
# print("{}的地址爲:{}".format(str_attr, obj_attr))
# 執行方法
print("{}(方法)的計算結果爲 {}".format(str_attr, obj_attr()))
else:
print("{}(屬性)的值爲{}".format(str_attr, obj_attr))
if __name__ == "__main__":
main()
控制檯輸出結果:
(1)直接調用對象方法
4
5
20
18
(2)實例化對象的反射
b(屬性)的值爲4
h(屬性)的值爲5
cal_area(方法)的計算結果爲20
cal_perimeter(方法)的計算結果爲18
(2)類對象的反射實例
class Rectangle:
"""矩形類"""
def __init__(self, b, h):
self.b = b
self.h = h
@classmethod
def show_me(cls):
return "大家好,我是{}".format(cls.__doc__)
@staticmethod
def show_me2():
return "我是一個Rectangle類中的靜態方法show_me2()"
def cal_area(self):
return self.b*self.h
def cal_perimeter(self):
return (self.b+self.h)*2
def main():
list_attr = ["__doc__", "show_me", "show_me2"]
for str_attr in list_attr:
if hasattr(Rectangle, str_attr):
obj_attr = getattr(Rectangle, str_attr)
if callable(obj_attr): # if hasattr(obj_attr, '__call__'): #判斷是否可調用,即是否爲方法
# 反射屬性(對象方法)的地址
# print("{}的地址爲:{}".format(str_attr, obj_attr))
# 執行方法
print("{}(方法)的計算結果爲 {}".format(str_attr, obj_attr()))
else:
print("{}(屬性)的值爲{}".format(str_attr, obj_attr))
if __name__ == "__main__":
main()
控制檯輸出結果:
__doc__
(屬性)的值爲矩形類
show_me(方法)的計算結果爲 大家好,我是矩形類
show_me2(方法)的計算結果爲 我是一個Rectangle類中的靜態方法show_me2()
(3)本模塊的反射實例
import sys
var1 = "我是來自selfpy.py中的變量var1"
def show_me():
return "我是來自selfpy.py中的show_me()"
def main():
# 獲取本模塊的對象
print("__name__的值爲%s" % __name__)
obj = sys.modules[__name__]
# (1)獲取屬性var1
str_attr = "var1"
print("(1)獲取屬性%s" % str_attr)
if hasattr(obj, str_attr):
print(getattr(obj, str_attr))
else:
print("未找到%s" % str_attr)
# 調用函數show_me()
# (2)獲取屬性var2
str_attr = "var2"
print("(2)獲取屬性%s" % str_attr)
if hasattr(obj, str_attr):
print(getattr(obj, str_attr))
else:
print("未找到%s" % str_attr)
# (3)調用函數show_me()
str_attr = "show_me"
print("(3)獲取屬性%s()" % str_attr)
if hasattr(obj, str_attr):
print(getattr(obj, str_attr))
print(getattr(obj, str_attr)())
else:
print("未找到%s" % str_attr)
if __name__ == '__main__':
main()
控制檯輸出結果:
__name__
的值爲__main__
(1)獲取屬性var1
我是來自selfpy.py中的變量var1
(2)獲取屬性var2
未找到var2
(3)獲取屬性show_me()
<function show_me at 0x000002964D70C268>
我是來自selfpy.py中的show_me()
知識加油站:
模塊或工具 | 說明 |
---|---|
sys | sys模塊是與python解釋器交互的一個接口 |
sys.modules | 一個全局字典,該字典是python啓動後就加載在內存中。每當導入新的模塊,sys.modules將自動記錄該模塊。當第二次再導入該模塊時,python會直接到字典中查找,從而加快了程序運行的速度。它擁有字典所擁有的一切方法。 |
(4)其他模塊的反射實例
現在我們準備兩個py文件:
- 其他py文件:otherpy.py
- 本py文件:selfpy.py
其他py文件otherpy.py
的代碼如下:
var1 = "我是來自otherpy.py中的變量var1"
def show_me():
return "我是來自otherpy.py中的show_me()"
本py文件selfpy.py
的代碼如下:
def main():
# 導入其它py文件(對象),NO1和NO2兩種方法選一種
# NO1:import object直接導入
# import otherpy as obj
# NO2:__import__(modules),其中modules爲對象的字符串名稱
# 實現了基於字符串的動態的模塊導入
obj = __import__("otherpy")
# (1)獲取屬性var1
str_attr = "var1"
print("(1)獲取屬性%s" % str_attr)
if hasattr(obj, str_attr):
print(getattr(obj, str_attr))
else:
print("未找到%s" % str_attr)
# 調用函數show_me()
# (2)獲取屬性var2
str_attr = "var2"
print("(2)獲取屬性%s" % str_attr)
if hasattr(obj, str_attr):
print(getattr(obj, str_attr))
else:
print("未找到%s" % str_attr)
# (3)調用函數show_me()
str_attr = "show_me"
print("(3)獲取屬性%s()" % str_attr)
if hasattr(obj, str_attr):
print(getattr(obj, str_attr))
print(getattr(obj, str_attr)())
else:
print("未找到%s" % str_attr)
if __name__ == '__main__':
main()
控制檯輸出結果:
(1)獲取屬性var1
我是來自otherpy.py中的變量var1
(2)獲取屬性var2
未找到var2
(3)獲取屬性show_me()
<function show_me at 0x0000013AFB2DA950>
我是來自otherpy.py中的show_me()
版權聲明:本文爲博主原創文章,如需轉載,請給出:
原文鏈接:https://blog.csdn.net/qq_35844043/article/details/104987746