面向对象----反射(自省)
vars(),dir(),locals()
vars()和dir()返回的结果有区别:
dir()和vars()的区别就是:dir()只打印属性,vars()则打印属性与属性的值。
a = 1 b = 2 print(vars()) #{...} 字典形式 key:value {变量名:值} print(dir()) #[...] 列表形式 key [变量名]
dir():
默认打印当前模块的所有属性,如果传一个对象参数则打印当前对象的属性
vars():
默认打印当前模块的所有属性,如果传一个对象参数则打印当前对象的属性
函数以字典形式返回参数中每个成员的当前值,如果vars函数没有带参数,那么它会返回包含当前局部命名空间中所有成员的当前值的一个字典。
locals() 不传参数(也不能传参数)的情况下,和vars() 一样 #{...} 字典形式 key:value {变量名:值}
class A: name = 1 b = 2 def func(self): print(111) dic = vars(A) print(dic['name']) #1 str = input("请输入:") # 类似eval print(dic['%s'%str]) #print(vars('%s'%str)) 用字符串操作变量名,函数名
-
class A: a = 1 b = 2 def __init__(self): self.c = 3 def func(self): print(111) a = A() print(vars(a)) #{'c': 3} 查看对象的属性
反射(自省)
什么是反射:
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。
python面向对象中的反射:
通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
四个可以实现自省的函数: 下列方法适用于类和对象(一切皆对象,类本身也是一个对象)
hasattr(obj,属性) #检测对象是否拥有这个属性 getattr(obj,属性) #查看对象 的属性 setattr(obj,属性,值) # 添加/修改 属性 delattr(obj,属性) # 删除属性
示例:
class Foo: def __init__(self,name): self.name = name def func(self): return 123 f = Foo('kitty') print(hasattr(f,'name')) #检测对象是否拥有这个属性 print(hasattr(f,'age')) #True #False print(getattr(f,'name')) #查看对象 的属性 #kitty a = getattr(f,'func') # 函数的内存地址 print(a()) # 函数的内存地址() 调用函数 # 123 print(getattr(f,'age','如果不存在,返回我')) #不设置第三个参数,会报错:'Foo' object has no attribute 'age' # 如果不存在,返回我 # 可以设置返回值 setattr(f,'age',18) # 添加新属性 print(f.age) # 18 setattr(f,'age',66) # 修改属性 print(f.age) # 66 setattr(f,'age_2',lambda self,n: n**2) print(f.age_2(f,4)) # 16 delattr(f,'age') print(f.age) ##AttributeError: 'Foo' object has no attribute 'age' print(getattr(f,'age','如果不存在,返回我')) #如果不存在,返回我
扩展:代码级别能解决的(能用if 解决的)问题, 就不用try except
还是上面的类和对象 import logging if hasattr(f,'job'): # 如果输入错误,就报错 print(getattr(f,'job')) else:logging.warning("不存在job属性") #WARNING:root:不存在job属性
注意:
getattr()拿到的只是一个名字
拿到方法名之后,如果要调用方法,需要加括号“()”
总结:
反射就是 使用字符串数据类型的变量名 获取属性值或调用方法
小结:
hasattr(类名,'属性名') 返回True或False
属性值 = getattr(类名,'属性名')
方法的内存地址 = getattr(类名,'方法名')
方法的内存地址()
#### 对象的空间没有 类的方法 在类里面
对象的反射
类的反射 (python一切皆对象,类也是对象)
模块的反射 (python一切皆对象,模块也是对象)
本模块的反射
a = 2 import sys obj = sys.modules['__main__'] #只有本模块可以用'__main__',但是,假如a模块引用b模块,就不行了(参考if __name__ = '__main__':) print(getattr(obj,'a')) # 2
-
a = 2 import sys obj = sys.modules[__name__] #万能写法 不管导入到任何模块,__name__都等于那个模块的名字 print(getattr(obj,'a')) # 2