反射的总结:
就是通过字符串来获取, 删除和设置对象的属性或方法
反射:反射是动态语言的一个重要特点,它允许你在运行时检查对象的属性和方法,以及修改它们。这为元编程和编写通用代码提供了支持。
什么是反射
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。
python面向对象中的反射:
通过字符串的形式操作对象相关的属性. python中的一切事物都是对象(都可以使用反射)
用户输入一段字符串, 执行该字符串对应的方法
其中前两点hasattr和getattr
这两种方法并用
# 四个可以实现自省的函数
# hasattr() # 判断一个属性是否在对象中; 返回True或False
# getattr() # 通过字符串获取属性或方法; 如果获取到了,就返回相应的属性或方法
# setattr() # 通过字符串来设置属性或方法
# delattr() # 通过字符串来删除属性或方法
class Foo:
def run(self):
print("run")
def speak(self):
print("speak")
f = Foo()
cmd = input("请输入命令:")
# 返回内存地址
# print(Foo.__dict__[cmd])
# 方案一:
# Foo.__dict__[cmd]()
# 方案二: 通过反射来实现
if hasattr(f, cmd):
run = getattr(f, cmd)
run()
else:
print("该命令不存在!")
另外两种方法setattr和delattr
setattr
;
class Foo:
def run(self):
print("run")
def speak(self):
print("speak")
f = Foo()
# 通过用户输入key和value往对象中赋值
key = input("请输入key:")
value = input("请输入value:")
# 原始
# f.key=value
# 反射
setattr(f, key, value)
print(f.age) # key输入什么就说写什么, 这里代码比较死
动态的往对象中放方法
class Foo:
def run(self):
print("run")
def speak(self):
print("speak")
f = Foo()
# 动态的往对象中放方法
def test(a):
print(a)
# 没添加前
print(f.__dict__)
# 添加后
setattr(f, 'test', test)
print(f.__dict__)
# 调用
f.test(666)
动态的往对象中删除放法
class Foo:
def run(self):
print("run")
def speak(self):
print("speak")
f = Foo()
# 原始删除方法
# f.name='nick'
# print(f.__dict__)
# del p.name
# print(f.__dict__)
# 动态的删除属性
# 动态删除f中的属性为变量a的属性
f.name='nick'
f.age=18
f.sex='male'
# 查看删除前的属性
print(f.__dict__.keys())
a = input("请输入要删除的属性:")
# 直接f.a删除是不对的
# del f.a
delattr(f, a)
# 查看删除后的属性
print(f.__dict__.keys())
例子总结
class BlackMedium:
feature='Ugly'
def __init__(self,name,addr):
self.name=name
self.addr=addr
def sell_house(self):
print('%s 黑中介卖房子啦,傻逼才买呢,但是谁能证明自己不傻逼' %self.name)
def rent_house(self):
print('%s 黑中介租房子啦,傻逼才租呢' %self.name)
b1=BlackMedium('万成置地','回龙观天露园')
#检测是否含有某属性
print(hasattr(b1,'name'))
print(hasattr(b1,'sell_house'))
获取属性 : getattr
# 如果第二个参数是属性则返回,属性对应的值 feature='Ugly'
n = getattr(b1, 'name')
print(n)
# 如果第二个参数是方法则返回,方法对应的内存地址,然后加括号调用
func = getattr(b1, 'sell_house')
func()
# getattr(b1,'aaaaaaaa') # 这里本来会报错, 但是我把第三个参数(默认值)改为字符串类型的('不存在啊!')就不会报错
print(getattr(b1, 'aaaaa', '不存在啊!'))
设置属性 : setattr
setattr(b1, 'my', True)
# 这里放置了一个匿名函数,不是绑定方法;调用的话有几个值就要传几个值
setattr(b1, 'my_gift', lambda self:self.name+'my')
print(b1.__dict__)
print(b1.my_gift(b1))
setattr
的重点
setattr
函数允许你在运行时动态设置对象的属性值。这是非常有用的,因为它允许你根据需要配置对象属性,而不必在代码中硬编码这些属性。
class dafen:
def __init__(self, name):
self.name = name
# 创建一个 Person 实例
p = dafen("Alice")
# 动态添加属性并设置其值
xueke = input("请输入课程名字:")
cj = input("请输入得分成绩:")
xueke2 = '数学'
cj2 = 102
setattr(p, xueke, cj)
setattr(p, xueke2, cj2)
if hasattr(p, xueke):
xueke = getattr(p, xueke)
print(xueke)
# 动态的删除你输入的属性
shanchu = input("请输入你要删除的学科:")
delattr(p, shanchu)
# 访问动态添加的属性
print(f"你{xueke}的成绩为{getattr(p, xueke)}")
删除属性 : delattr
delattr(b1, 'abbr')
delattr(b1, 'my_gift')
# 如果没有该方法,则报错
delattr(b1, 'wo_diu')
print(b1.__dict__)