python反射

python反射

python的反射是基于字符串的形式去对象(模块)中操作其成员。此操作是动态的,常用于web开发中url参数中对应模块或者函数的反射。
下面开始具体说明:

  • 场景需求:

我的python脚本中有一百个函数,当前端页面被访问到之后,针对特定的url 我后端有特定的函数进行处理,我该如何判断这个URL需要后端那个函数来处理呢?写if判断?别闹了。一百多个呢,那执行效率会有多慢。看下面代码:

def f1():
    print("f1")

def f2():
    print("f2")


def f3():
    print("f3")

res = input("请输入url: ")
if res == 'f1':
    f1()
elif res == 'f2':
    f2()
elif res == 'f3':
    f3()
else:
    print("404")
    
执行结果:
请输入url: f1
f1

请输入url: f2
f2

请输入url: f3
f3

请输入url: adasd
404

 

现在是定义了3个函数,如果100个的,我得写100个if判断,那不疯了。。。
下面耍个小聪明,使用dict映射来做

def f1():
    print("f1")

def f2():
    print("f2")


def f3():
    print("f3")

func_map = {
    'f1':f1,
    'f2':f2,
    'f3':f3,
}
res = input("请输入url: ")

if res in func_map:
    func_map[res]()
else:
    print('404')
    
 输出结果:
 
 
请输入url: f1
f1

请输入url: f2
f2

请输入url: f3
f3

请输入url: asdad
404

 

发现还是很麻烦。字典需要写很长影射,而且后期我加一个函数,还得在字典中手动添加对应的影射关系,万一写错了。就悲催了。。。。下面反射就出来了,就可以很好解决此问题!

  • 反射getattr处理
class getfunc():
    def f1(self):
        print("f1")

    def f2(self):
        print("f2")


    def f3(self):
        print("f3")

res = input("请输入url: ")

obj_func = getfunc()
func = getattr(obj_func,res)
func()

输出结果:


请输入url: f1
f1

请输入url: f2
f2

请输入url: f3
f3

请输入url: f4
Traceback (most recent call last):
  File "反射.py", line 55, in <module>
    func = getattr(obj_func,res)
AttributeError: 'getfunc' object has no attribute 'f4'

 

这里我们使用的是类的作法,先创建一个类,将所有函数放在类里。在调用前先实例化该类,不论类里有多少个函数,直接根据输入内容通过getattr调用类里的函数。这样后期不管添加多少函数,只要前端能调用符合要求,则都会被调到。
发现最后一个怎么报错?原来并没有匹配到f4这个函数。反射也提供了检查功能,类似于检查一个字典是否存在某个key一样。下面说明一下反射的基本操作类型

  • 反射的操作类型:
    • getattr() 查找
    • setattr() 设置
    • hasattr() 判断
    • delattr() 删除 接着上面的类说明操作类型的用法:
class getfunc:
    def __init__(self):
        self.test = '1234'
    def f1(self):
        print("f1")

    def f2(self):
        print("f2")


    def f3(self):
        print("f3")

foo = getfunc()
print(hasattr(foo,'f1'))    判断是否有f1
print(hasattr(foo,'f5'))        判断是否有f5

print(setattr(foo,'f5','f1'))   设置f5为f1
print(getattr(foo,'f5'))    判断是否有f5

print(delattr(foo,'test'))  删除test
print(hasattr(foo,'test'))   判断是否有test

运行结果:
True
False
None
f1
None
False

 

同样模块也支持动态导入,看下面说明:

  • 反射模块

模块动态导入使用__import__方法

定义一个模块:fanshe
def login():
    print('登录页面')


def logout():
    print('退出页面')


def home():
    print("主页面")

下面是调用代码:
inp = input("请输入url:")
m,f = inp.split('/')
try:
   obj = __import__(m)
except:
   print("404")
   sys.exit()
if hasattr(obj,f):
   func = getattr(obj,f)
   func()
else:
   print("404")

执行结果:

请输入url:fanshe/login
登录页面

请输入url:fanshe/logout
退出页面

请输入url:fanshe/home
主页面

 

反射太强大了。

posted @ 2016-06-18 09:28  Fuzengjie  阅读(342)  评论(0编辑  收藏  举报