21 反射
21.1 反射概念
反射主要是指程序可以访问、检测和修改其本身状态或行为的一种能力。在Python中最重要的4个方法如下所示:
- getattr:获取指定字符串名称的对象属性
- setattr:给对象添加类属性
- hasattr:判断对象是否存在某个对应的对象
- delattr:删除指定的属性
我们先来定义一个类,如下所示:
class Fruit:
def __init__(self,name,color):
self.name=name
self.color=color
def __str__(self):
return f"Fruit is {self.name} color is {self.color}"
def buy(self,price,totalWeight):
return f"Fruit is {self.name},total price is {price*totalWeight}"
21.2 反射常用方法
21.2.1 getattr
getattr主要用来获取指定字符串名称的对象属性,其使用方法如下所示:
getattr(object, name:string[, default]) -> value
- name参数需要为string类型,不管是判断类属性还是类方法,其名称均以字符串形式传参
- 如果属性存在,则返回其属性值,不存在则分为两种情况,一种是没有default参数时,则直接报错,如给定了default参数,对象没有其属性,则返回给定的default值
- 如果获取的是类方法,则返回函数对象
以前面定义的Fruit类为例
# 实例化一个类
apple=Fruit("apple","red")
# 利用反射获取类属性
print(getattr(apple,"name"))
print(getattr(apple,"color"))
# 利用反射获取类方法
print(getattr(apple,"buy"))
# 利用反射获取不存在的属性且有默认值
print(getattr(apple,"test","123"))
# 利用反射获取不存在的属性且没有默认值 - 报错
print(getattr(apple,"test"))
输出结果如下所示:
apple
red
<bound method Fruit.buy of <__main__.Fruit object at 0x000001E70B356288>>
123
Traceback (most recent call last):
File "C:/Users/Surpass/Documents/PycharmProjects/SADCI/TempCode/reflectorSample.py", line 24, in <module>
print(getattr(apple,"test"))
AttributeError: 'Fruit' object has no attribute 'test'
21.2.2 setattr
setattr主要用于给对象添加一个类属性,如果添加的属性已经存在,则对其进行更新,否则则进行创建,其使用方法如下所示:
setattr(object, name:string, value)
name参数需要为string类型,不管是判断类属性还是类方法,其名称均以字符串形式传参
示例如下所示:
# 实例化一个类
apple=Fruit("apple","red")
# 为实例添加一个类属性,并设置其值
setattr(apple,"destination","china")
print(f'第一次添加类属性,其值为(添加操作):{getattr(apple,"destination")}')
setattr(apple,"destination","USA")
print(f'第二次添加类属性,其值为(更新操作):{getattr(apple,"destination")}')
输出结果如下所示:
第一次添加类属性,其值为(添加操作):china
第二次添加类属性,其值为(更新操作):USA
21.2.3 hasattr
hasattr常用于判断对象中是否存在其属性或方法,常用用法如下所示:
hasattr(object, name:string) -> bool
name参数需要为string类型,不管是判断类属性还是类方法,其名称均以字符串形式传参
示例如下所示:
# 实例化一个类
apple=Fruit("apple","red")
# 判断属性或方法是否存在
print(f'对象是否存在其属性 name - {True if hasattr(apple,"name") else False }')
print(f'对象是否存在其属性 country - {True if hasattr(apple,"country") else False }')
print(f'对象是否存在其方法 buy - {True if hasattr(apple,"buy") else False }')
输出结果如下所示:
对象是否存在其属性 name - True
对象是否存在其属性 country - False
对象是否存在其方法 buy - True
21.2.4 delattr
delattr常用于删除指定的属性,但不能用于方法,常用用法如下所示:
delattr(object, name:string)
name参数需要为string类型,不管是判断类属性还是类方法,其名称均以字符串形式传参
示例如下所示:
# 实例化一个类
apple=Fruit("apple","red")
delattr(apple,"name")
# 判断属性或方法是否存在
print(f'对象是否存在其属性 name - {True if hasattr(apple,"name") else False }')
print(f'对象是否存在其属性 country - {True if hasattr(apple,"country") else False }')
print(f'对象是否存在其方法 buy - {True if hasattr(apple,"buy") else False }')
输出结果如下所示:
对象是否存在其属性 name - False
对象是否存在其属性 country - False
对象是否存在其方法 buy - True
在日常使用,一般会进行判断属性是否存在,然后再调用获取、添加和删除方法
21.3 示例
以下用一个简单的示例来解释,反射在实际的应用案例。现在有一个场景,就是根据传入的不同的模块名称,调用不同的模块所对应方法,代码如下所示:
class ReflectSample:
def moduleA(self):
print("我是moduleA")
def moduleB(self):
print("我是moduleB")
def moduleC(self):
print("我是moduleC")
def moduleD(self):
print("我是moduleD")
- 方法一:
while True:
reflectSample=ReflectSample()
choice=input("请输入模块名称")
if choice == "moduleA":
reflectSample.moduleA()
elif choice == "moduleB":
reflectSample.moduleB()
elif choice == "moduleC":
reflectSample.moduleC()
elif choice == "moduleD":
reflectSample.moduleD()
else:
print("输入的模块不存在")
测试结果如下所示:
请输入模块名称moduleA
我是moduleA
请输入模块名称moduleD
我是moduleD
请输入模块名称moduleF
输入的模块不存在
- 方法二:
while True:
reflectSample = ReflectSample()
choice = input("请输入模块名称")
if hasattr(reflectSample,choice):
func=getattr(reflectSample,choice)
func()
else:
print("输入的模块不存在")
测试结果如下所示:
请输入模块名称moduleA
我是moduleA
请输入模块名称moduleD
我是moduleD
请输入模块名称moduleF
输入的模块不存在
两种方法一对比,自然就觉得方法二更简洁,也更容易维护,更不用担心类中有很多个方法。
本文地址:https://www.cnblogs.com/surpassme/p/12902742.html
本文同步在微信订阅号上发布,如各位小伙伴们喜欢我的文章,也可以关注我的微信订阅号:woaitest,或扫描下面的二维码添加关注: