日期: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