def getattr(object, name, default=None):
pass
参数:
- 参数一:类对象或模块
- 参数二:字符串
场景:根据用户输入来调用执行不同的函数,类似于 Django
、flask
等 Web
框架的路由系统。
常规写法
1、common.py
def login():
print("这是一个登陆页面!")
def logout():
print("这是一个退出页面!")
def home():
print("这是网站主页面!")
2、visit.py
import common
def run():
inp = input('请输入你的 URL:').strip()
if inp == "home":
common.home()
elif inp == "login":
common.login()
elif inp == "logout":
common.logout()
else:
print('404 not found')
if __name__ == '__main__':
run()
优缺点:
common.py
有多少函数,就要判断多少次,代码重复性较高getattr 反射写法
visit.py
import common
def run():
inp = input('请输入你的 URL:').strip()
func = getattr(common, inp)
func()
if __name__ == '__main__':
run()
优缺点:
参数与 getattr
一致,用于判断对象、模块是否具有某个字符串
def hasattr(*args, **kwargs):
pass
上面 visit.py
有个缺点,当用户输入的 URL
,common.py
中没有时会报错:AttributeError: module 'commons' has no attribute 'xxx'
.
这是因为 common.py
中没有 xxx()
函数所致,解决办法就是使用 hasattr()
判断是否有该函数,再 getarrt()
,改造后如下:
import common
def run():
inp = input('请输入你的 URL:').strip()
if hasattr(common, inp):
func = getattr(common, inp)
func()
else:
print('404')
if __name__ == '__main__':
run()
上述示例固然好,但有一个缺点:就是 common.py
和 visit.py
必须在同一级目录。而实际生产环境中,往往各个功能模块分布在不同文件夹中,若想实现上述功能,那么就需要在 visit.py
写入大量的 import
语句。
实际上可以通过 Python
的动态导入模块,动态导入要执行的功能函数模块,避免写过多的重复代码。
__import__(name)
Python内置的__import__(字符串参数)
函数可以实现类似 getattr()
的反射功能。__import__()
方法会根据字符串参数,动态地导入同名的模块。
1、目录结构:
│─account.py
│─common.py
│─manage.py
│─visit.py
│
└─__pycache__
2、visit.py
def run():
inp = input('请输入你的 URL:').strip()
modules, func = inp.split('/') # common/home
obj = __import__(modules)
if hasattr(obj, func):
func = getattr(obj, func)
func()
else:
print('404')
if __name__ == '__main__':
run()
Tips:输入的时候要同时提供模块名和函数名字,并用斜杠分隔
跨包问题
同样地,上述动态导入模块,当出现跨包时,也会导致出现模块导入问题,即 visit.py
与其他功能模块不在同一级目录。
1、目录结构:
│─visit.py
│
├─lib
│ account.py
│ common.py
│ manage.py
│
└─__pycache__
2、visit.py
def run():
inp = input('请输入你的 URL:').strip()
modules, func = inp.split('/')
obj = __import__("lib." + modules)
if hasattr(obj, func):
func = getattr(obj, func)
func()
else:
print('404')
if __name__ == '__main__':
run()
运行结果:
请输入你的 URL:common/home
404
common.py
明明有 home()
函数,却提示 404。这是因为 __import__
默认只会导入最开头的圆点左边的目录,也就是lib
,后面的不会导入,除非加上fromlist=True
这个参数:
obj = __import__("lib." + modules, fromlist=True)
运行结果:
请输入你的 URL:common/home
这是网站主页面!
参考文章:http://www.liujiangblog.com/course/python/48