一、反射的定义
反射的本质:
是通过字符串去调用某个对象的方法/属性,或者调用模块中的函数等。
通俗点说:
用字符串数据类型的名字 来操作这个名字对应的 函数\实例变量\绑定方法\各种方法
二、python中提供了四个重要的方法
- getattr() 获取对象属性/对象方法
- hasattr() 判断对象是否有对应的属性及方法
- delattr() 删除指定的属性
- setattr() 为对象设置内容
hasattr | 查询 |
setattr | 新增 |
getattr | 获取 |
delattr | 删除 |
class Person:
# 类属性
Role = "法师"
# 私有属性
__weight = 120
def __init__(self):
# 实例属性
self.name = 'mike'
self.age = 20
# 普通方法
def say(self):
return '普通方法'
# 私有方法
def __say2(self):
return '私有方法'
# 类方法
@classmethod
def say3(cls):
obj = Person()
print(obj.name)
return '类方法'
1、getattr()方法
这个方法是根据字符串去某个模块中寻找方法等
1.1、反射对象的 普通属性/普通方法
obj = Person()
print(getattr(obj, 'name')) # 反射对象的 普通变量 正常用法是 obj.name
print(getattr(obj, 'say')) # 方法的内存地址 后面结()表示执行这个方法
getattr(obj, 'say')() # 反射对象的 普通方法 正常用法是 obj.say()
################################################
mike
<bound method Person.say of <__main__.Person object at 0x00000206296B4EE0>>
普通方法
Process finished with exit code 0
1.2、反射类的 类属性/类方法
print(getattr(Person, 'Role')) # 反射类中的 类属性 正常用法是 Person.Role
getattr(Person, 'say3')() # 反射类中的 类方法 正常用法是 Person.say3()
#######################################################
法师
mike
类方法
Process finished with exit code 0
1.3、反射当前脚本的 变量/函数
import sys
name = 'mike'
def func1():
print('普通函数')
# 反射当前脚本的变量 正常应该是 print(name)
obj = getattr(sys.modules['__main__'],'name')
print(obj)
# 反射当前脚本的函数 正常应该是 func1()
obj = getattr(sys.modules['__main__'],'func1')
obj()
##############################################################
mike
普通函数
Process finished with exit code 0
1.4、反射被导入模块的 变量/函数
被导入模块 test04.py
name = 'mike' def func1(): print('普通函数')
当前脚本 a.py
import test04 # 反射被导入模块的变量 正常应该是 test04.name obj = getattr(test04, 'name') print(obj) # 反射被导入模块的方法 正常应该是 test04.func1() obj = getattr(test04, 'func1') obj() ################################################ mike 普通函数 Process finished with exit code 0
2、hasattr()方法
这个方法是根据字符串去判断某个模块中该方法是否存在 返回布尔类型
obj = Person()
# 判断对象是否有某个属性
print(hasattr(obj, 'name'))
print(hasattr(obj, 'xxx'))
#################################################
True
False
Process finished with exit code 0
拓展:
封装一个函数结合getattr()方法和callable()方法使用
def fanshe(a,b):
# 判断类或者对象 能不能反射某一个变量 如果能反射返回True
if hasattr(a, b):
# 判断能反射的变量是不是一个方法,如果是可执行的,如果是我们直接可以调用
if callable(getattr(a, b)):
# 执行方法
getattr(a, b)()
else:
# 打印属性
print(getattr(a, b))
else:
print('没有这个属性/方法')
a = Person()
# 反射一个对象里不存在的属性
b = 'xxx'
fanshe(a,b)
# 反射一个对象存在属性
b = 'name'
fanshe(a,b)
# 反射一个对象不存在方法
b = 'say222222'
fanshe(a,b)
# 反射一个对象存在方法
b = 'say'
fanshe(a,b)
#########################################
没有这个属性/方法
mike
没有这个属性/方法
普通方法
Process finished with exit code 0
3、setattr()方法
这个方法是根据字符串去某个模块中设置方法,可以动态添加属性和方法
obj = Person()
# 修改之前 anme 属性
print(getattr(obj, 'name'))
setattr(obj, 'name', "吴彦祖")
# 修改之后 name 属性
print(getattr(obj, 'name'))
#######################################################################
mike
吴彦祖
Process finished with exit code 0
4、delattr()方法
这个方法是根据字符串去某个模块中删除方法
obj = Person()
# 删除之前判断是否有这个属性,如果有则打印
if hasattr(obj, 'age'):
print(getattr(obj, 'age'))
else:
print('没有这个属性')
# 删除该属性
delattr(obj, 'age')
# 建议是否已经删除
if hasattr(obj, 'age'):
print(getattr(obj, 'age'))
else:
print('没有这个属性')
##################################################################
20
没有这个属性
Process finished with exit code 0