一、反射
python 中用字符串的方式操作对象的相关属性,python 中一切皆对象,都可以使用反射
用eval 有安全隐患,用 反射就很安全
1.反射对象中的属性和方法
class A: a_class = '反射类静态属性' @classmethod def func_class(cls): return '反射类方法' def __init__(self, name): self.name = name print('%s是对象属性' % (self.name)) def func(self): return '反射对象方法'
2、getatter 获取
1. 反射对象中的属性和方法
a = A('zzy') # zzy是对象属性 实例化的时候会触发init,打印zzy是对象属性
原版:a.name ret = getattr(a, 'name') # print(ret) # zzy
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
原版:a.func() ret2 = getattr(a, 'func') print(ret2) #<bound method A.func of <__main__.A object at 0x01B5EBB0>>打印的是函数地址,并没有调用 ret2() #加括号就表示调用,打印‘对象方法’ 简洁版 print(getattr(a, 'name')) #zzy是对象属性,zzy print(getattr(a,'func')()) #反射对象方法
2.反射类的静态属性和方法
#原版:A.func_class() print(getattr(A,'func_class')()) #zzy是对象属性 print(getattr(a,'func_class')()) #反射类方法---->>用对象调用类方法也可以,但是不推荐, #原版:A.a_class print(getattr(A,'a_class')) #反射类静态属性
""" 注释:getattr (对象/类,‘属性/方法’) 属性/方法必须是字符串形式 getattr 反射方法的时候,要在末尾加(),才能算是调用,否则打印的只是函数地址 """
要反射的函数有参数怎么办?
# print(time.strftime('%Y-%m-%d %H:%M:S')) # print(getattr(time,'strftime')('%Y-%m-%d %H:%M:S'))
3、hasattr 有
#判断需要反射的对象是否存在,和getattr是夫妻档,判断存在的时候,才会执行getattr if hasattr(a,'name'): print(getattr(a,'name')) # zzy是对象属性 zzy
4、setattr 设置修改变量
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
class A: pass a = A() setattr(a,'name','nezha') #在对象a中新建属性name属性,并且赋值'nezha' setattr(A,'name','alex') #在A类中新建静态属性name属性,并且赋值'alex' print(A.name) #alex print(a.name) #'nezha
5、delattr 删除一个变量
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
delattr(a,'name') #删除对象a中新建属性name属性 print(a.name) #删除后打印会报错 delattr(A,'name') #删除在A类中新建静态属性name属性 print(a.name) #删除后打印会报错
6、进阶使用1,涉及用户交互
变量名=input('请输入:') print(getattr(a,变量名)) #zzy
练习,需求:用户输入time 和 asctime打印出time.time/asctime
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
import time t=input('请输入:') #输入time / asctime print(getattr(time,t)()) # 因为输入的是time / asctime,而 #注释:说明内置函数也是可以反射的
7、进阶使用2,涉及其他导入模块的反射
(1)反射其他模块
import sys import model b=model.B('zzy') #反射模块的类属性 原版:print(b.name) print(getattr(b,'name')) #zzy #反射模块类方法 原版: b.func1() print(getattr(b,'func1')()) #你好
(2)反射模块中变量
import model
#原版:model.soga # model模块 中有soga=input('请输入:')
print(getattr(model,'soga')) #打印你输入的内容 #反射模块中的函数
# 原版model.foo()
print(getattr(model,'foo')('zxc')) #zxc 函数中有参数的话,就可以在括号里('zxc')传进去
(3)反射模块中的函数
# 原版model.foo() # print(getattr(model,'foo')('zxc')) #zxc 函数中有参数的话,就可以在括号里('zxc')传进去
8、进阶3:反射自己模块
(1)导入自己模块的变量
msg=1+2print(getattr(sys.modules['__main__'],'msg')
(2)导入自己模块的函数
def foo (a): return a print(getattr(sys.modules[__name__],'foo')('zxc')) #zxc
(3)反射自己模块的类
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
class C: a_class = '反射模块类静态属性' @classmethod def func_class(cls): return '反射模块类方法' def __init__(self, name): self.name = name @property def func_c(self): return '反射模块对象方法' @staticmethod def func(): return '我是一个普通的函数'
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
import sys c=C('ZZY') print(getattr(sys.modules['__main__'],'C')) #<class '__main__.C'> 类的函数地址 print(getattr(sys.modules['__main__'],'c')) #<__main__.C object at 0x01B77210> 对象的函数地址 print(getattr(sys.modules['__main__'],'c').name) #ZZY 对象.name 就可以调用自己模块中类的方法名了 print(getattr(sys.modules['__main__'],'C').func_class()) #反射模块类方法 print(getattr(sys.modules['__main__'],'c').func_c) #反射模块对象方法 print(getattr(sys.modules['__main__'],'C').func()) #我是一个普通的函数 #注释:sys.modules['__main__']找到当前运行的模块 #最好用sys.modules['__name__'],因为__name__ 永远获取的是__name__所在的模块
9、比较区别
先在一个reflect.py文件中打印
print(sys.modules[__name__])
print(sys.modules['__main__'])
再在另一个model.py文件在中执行下列
import reflect #导入reflect模块了,就会执行reflect模块中的程序 #reflect 中运行了print(sys.modules[__name__]) 就会打印:<module 'reflect' from 'D:\\Users\\ZhaoYun Zhu\\PycharmProjects\\reflect.py'> # reflect 中运行了print(sys.modules[__main__]) 就会打印:<module '__main__' from 'D:/Users/ZhaoYun Zhu/PycharmProjects//model.py'> # 总结:sys.modules['__main__']找到当前运行的模块 # 最好用sys.modules['__name__'],因为__name__ 永远获取的是__name__所在的模块