Python的反射机制
Python的反射机制,就是反射就是通过字符串的形式,导入模块;通过字符串的形式,去模块寻找指定函数,并执行。利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动!
常用的反射内置函数有四个:hasattr(),getattr(),setattr()和delattr()。我们来看看具体应该怎么使用。
首先定义一个类并实例化,再定义个字符串变量从键盘输入。
1 def cry(self): 2 print("%s is crying!"%self.name) 3 class Person(object): 4 def __init__(self,name): 5 self.name = name 6 def eat(self): 7 print("%s is eating "%(self.name)) 8 def talk(self): 9 print(("%s is talking"%self.name)) 10 p1 = Person("Jack") 11 action = input(">>>:")
要想用输入的字符串来调用实例中的属性或功能,用p1.action是不行的
>>>:eat Traceback (most recent call last): File "D:/python/week7/反射.py", line 14, in <module> p1.action AttributeError: 'Person' object has no attribute 'action'
最简单暴力的方法有一种:
class Person(object): def __init__(self,name): self.name = name def eat(self): print("%s is eating "%(self.name)) def talk(self): print(("%s is talking"%self.name)) p1 = Person("Jack") action = input(">>>:") if action == 'eat': p1.eat() elif action == 'talk': p1.talk()
可是如果类里定义了上百中功能,靠if来比较输入字符串显然是不靠谱的,也太low了。这时候,就用上反射了。
1 class Person(object): 2 def __init__(self,name): 3 self.name = name 4 def eat(self): 5 print("%s is eating "%(self.name)) 6 def talk(self): 7 print(("%s is talking"%self.name)) 8 p1 = Person("Jack") 9 action = input(">>>:") 10 if hasattr(p1,action): #hasattr(obj,func_str):判定实例内是否有名字为str的功能或属性 11 print(getattr(p1,action)) #gatattr(obj,func_str):返回实例内名字为str的功能的地址或属性的值
如果action = name,运行结果为Jack,如果action=eat,则返回值为eat()在内存中的地址
通过hasattr()函数来判定实例内是否包含输入名字和字符串一致的属性或功能,返回值为Ture 或False 就可以和if等指令配合使用。
注意getattr()的返回值,如果输入字符串的是属性名字,则返回值为属性的值,而输入的是功能的名字,返回值就是地址,换句话说在地址后加(),并在括号内加上实参,就能运行函数。
1 class Person(object): 2 def __init__(self,name): 3 self.name = name 4 def eat(self,food): #这里加了个形参 5 print("%s is eating %s"%(self.name,food)) 6 def talk(self): 7 print(("%s is talking"%self.name)) 8 p1 = Person("Jack") 9 action = input(">>>:") 10 if hasattr(p1,action): 11 done = getattr(p1,action) 12 done("cake") #在这里给形参food传递实参
>>>:eat Jack is eating cake
setattr()用来对实例的属性或功能进行更改或添加。
1 def cry(self): #定义了一个类里没有的函数 2 print("%s is crying!"%self.name) 3 class Person(object): 4 def __init__(self,name): 5 self.name = name 6 def eat(self,food): 7 print("%s is eating %s"%(self.name,food)) 8 def talk(self): 9 print(("%s is talking"%self.name)) 10 p1 = Person("Jack") 11 action = input(">>>:") 12 if hasattr(p1,action): 13 pass 14 else: 15 setattr(p1,action,cry) #setattr(obj,a,b)把名为b的功能添加在obj中,新功能/属性名为a 16 done = getattr(p1,action) 17 done(p1) #这里比把p1作为实参传递给新添加的功能
>>>:cry Jack is crying!
在上例中输入字符串为“cry”,实例中没有,就通过setattr()增加新的功能。然后用getattr()调用新添加的功能,这里一定要把实例作为实参传给新添加的功能(因为定义的cry需要调用实例里的属性)
setattr()还可用作更改实例的属性,如果属性内不含输入的字符串,则增加新的属性。
1 setattr(p1,action,"Lucy") 2 print(p1.name) #在输入name后,p1的name就编程Lucy了。
最后,delattr()用来删除实例中的属性或功能具体用法就是delattr(obj,str)删除boj内名为str的功能或属性。