本文共 1878 字,大约阅读时间需要 6 分钟。
Python里面反射指的是可以通过字符串在对象里面(比如一个模块)去操作(查找,删除,判断)一个成员(比如这个模块里面的函数)。
比如目前所学的知识,我们需要在模块s1.py中调用一个函数f1,我们需要导入s1.py,然后才能执行f1()
1 2 | import s1 s1.f1() |
如果一个大型软件有几百上千个函数需要调用,那么这样写起来会很累。一个简单的方法是反射。
比如一个简单的例子,从index里面调用commons
commons.py
1 2 3 4 5 6 7 8 9 | #!/usr/bin/env python # -*- coding:utf-8 -*- # Author Yuan Li def login(): print ( "Login Page" ) def logout(): print ( "Logout Page" ) def home(): print ( "Home Page" ) |
例1:
index.py
1 2 3 4 5 6 7 8 9 10 | import commons def run(): inp = input ( "Please input a url" ) if inp = = 'login' : login() elif inp = = 'logout' :logout() elif inp = = 'home' :home() else : print ( 404 ) if __name__ = = '__main__' : run() |
例2:
我可以通过反射的方式简化上面的操作:hasattr()可以判断一个对象里面是否包含一个成员;getattr()则是获取这个成员。这样无论我在commons里面定义了多少个函数,我都可以通过字符串去直接获取了
index.py
1 2 3 4 5 6 7 8 9 10 11 12 | import commons def run(): inp = input ( "Please input the Url.\n>>>>" ) if hasattr (commons,inp): func = getattr (commons,inp) func() else : print ( "404" ) if __name__ = = '__main__' : run() |
例3:
在例2 的基础上再进一步,如果我们有很多模块,每个模块里面又有很多函数,应该如何处理?当然可以手动import 所有的模块,但是如果模块数目很多,这样也很繁琐。导入模块同样可以通过反射的方式来简化。比如我输入 admin/login,前面的admin表示模块名,后面的login表示这个模块里面的函数名就行了。_import_()可以直接输入字符串的名字来加载对应的模块
1 2 3 4 5 6 7 8 9 10 11 12 | def run(): inp = input ( "Please input the Url.\n>>>>" ) m, f = inp.split( '/' ) obj = __import__ (m) if hasattr (obj,f): func = getattr (obj,f) func() else : print ( "404" ) if __name__ = = '__main__' : run() |
例4. 在例3的基础上再进一步,如果这些模块文件在其他的目录下,应该如何调用?
如果我们直接使用 _import_("lib.XX.YY"),那么他只会导入lib这个目录,为了正确识别整个路径,需要添加一个选项 fromlist=True
1 2 3 4 5 6 7 8 9 10 11 12 | def run(): inp = input ( "Please input the Url.\n>>>>" ) m, f = inp.split( '/' ) obi = __import__ ( "lib." + m,fromlist = True ) if hasattr (obj,f): func = getattr (obj,f) func() else : print ( "404" ) if __name__ = = '__main__' : run() |