模块讲解----反射 (基于web路由的反射)
一、反射的实际案例:
1 def main(): 2 menu = ''' 3 1、账户信息 4 2、还款 5 3、取款 6 4、转账 7 5、账单 8 ''' 9 10 menu_dic = { 11 '1':account_info, 12 '2':repay, 13 '3':withdraw, 14 '4':transfer, 15 '5':pay_check, 16 } 17 18 while True: 19 print(menu) 20 user_option = input(">>: ").strip() 21 if user_option in menu_dic: 22 menu_dic[user_option]() 23
反射的总结
1、实例:基于实例来说,就是伪造了web框架的路由系统,即通过一个URL,去定义到某一个模块中的函数上。
2、反射:基于字符串的形式去对象(模块)中,操作其成员。
getattr, delattr,setattr,hasattr
3、扩展:导入模块
import xxx
from xxx import ooo
obj = __import__("xxx")
obj = __import__("xxx.oo.xxx"+m, fromlist=True)
基础环境:
1、假如有个网页,需要根据用户输入的不同的url路径来展现,不同的页面内容。
2、定义两个模块:commons index
1、commons模块:(模拟不同功能的页面函数)
1 ''' 2 根据用户输入的url不同,调用不同的函数。 3 调用不同的函数,返回不同页面的内容。 4 ''' 5 6 7 def login(): 8 print('炫酷登录页面') 9 10 11 def logout(): 12 print('炫酷退出页面') 13 14 15 def home(): 16 print('炫酷主页面')
2、index模块:(判读用户输入url的不同,返回不同的结果)
1 ''' 2 判断用户输入的url的不同,显示不同的结果 3 ''' 4 5 import commons 6 7 def run(): 8 inp = input('请输入要访问的url>>>') 9 if inp == 'login': 10 commons.login() 11 elif inp == 'logout': 12 commons.logout() 13 elif inp == 'home': 14 commons.home() 15 else: 16 print('404') 17 18 19 if __name__ == '__main__': 20 run()
问题:
1、以上是一个网站的三个函数,也是三个页面功能。
2、现实中,一个网站中有多个页面(成百上千个函数),来处理用户的请求。
3、用户访问很多的页面,访问页面越多,那处理访问请求的函数就不一样。
解决方法:
1、在commons模块中要定义好多个页面功能函数,这个不变有多少定义多少。
2、在index中,无需多个if判断,只需要将用户输入的input值,自动匹配commons模块里的函数就OK了。
修改方法如下:
inp = input(’请输入要访问的url>>> ‘)
1 #inp获取到的是字符串类型。 inp = “login” 2 #commons.inp() != commons.login #回去找inp函数,然后执行 3 #利用字符串的形式去对象(模块)中,去操作(寻找/检查/删除/设置)成员,反射 4 getattr(commons,inp) 5 hasattr(commons,inp) 6 setattr() 7 delattr()
反射的使用方法
一、通过反射,寻找/检查模块成员:
1 import commons 2 3 def run(): 4 inp = input("请输入要访问的url>>> ") 5 6 #判断模块中的方法是否存在: 7 if hasattr(commons,inp): #判读模块内的方法是否存在,如果返回为True则调用。 8 9 #获取模块中包含的成员:getattr(模块名,用户输入的url) 10 func = getattr(commons,inp) 11 func() 12 13 else: #如果返回False则打印错误信息 404。 14 print(404) 15 16 17 if __name__ == '__main__': 18 run()
二、字符串模式的寻找、导入模块:
1、特点:基于web框架的URL路由模式的反射
2、用途:用户输入的url路径转成字符串的格式,然后调用相应的模块名和方法:
例如:account/login
3、分析:该需求分为2部分:
第一部分是:将用户输入的url转成字符串。
第二部分是:利用反射的方式通过字符串调用相应的模块和方法:
1 def run(): 2 inp = input('请输入要访问的rul>>> ') #获取url 3 m,f = inp.split('/') #将url转换成字符串 4 obj = __import__(m) #导入字符串中的模块 5 6 if hasattr(obj,f): #用内置函数判断字符串中的函数和方法是否存在, 7 func = getattr(obj,f) #如果存在,就调用字符串中的模块和方法 8 func() #执行调用方法 9 10 else: #如果不存在则打印404 11 print(404) 12 13 14 if __name__ == '__main__': 15 run() #本地函数调用 16 17 18 19 显示结果: 20 请输入要访问的rul>>> commons/db_mgs 21 炫酷的数据库连接信息:
三、导入同级文件夹下的模块:
注意:__import__:在默认的时候只导入lib.xx的点前面那个lib模块;
解决方法:需要用字符串拼接("目录名." + 模块名)
后参数(fromlist=True)
1、目录结构:
1 |day6 2 --| index.py 3 -- | lib 4 --| account.py 5 --| manager.py 6 --| commons.py
2、案例:
def run(): inp = input('请输入url路径>>>') m,f = inp.split('/') obj = __import__("lib."+m, fromlist=True) if hasattr(obj,f): func = getattr(obj,f) func() if __name__ == '__main__': run() 显示结果: 请输入url路径>>>manger/order 炫酷的订单页面:
练习:
1 #1、定义函数标题: 2 #登录&注册 3 login_register = ''' 4 1、登录 5 2、注册 6 3、退出 7 ''' 8 9 login_register_dic = { 10 '1':'acc_login', 11 '2':'acc_auth', 12 '3':'quit' 13 } 14 15 16 17 #2、定义函数体 18 def acc_login(): 19 print('this is login') 20 21 22 def acc_auth(): 23 print('This is auth') 24 25 26 def quit(): 27 print("This is quit") 28 29 30 31 #3、定义反射条件: 32 from core import logger 33 from core import login 34 from core import menu 35 def run(): 36 ''' 37 被调用的主接口,主要功能如下: 38 1、展示登录注册信息 39 2、通过反射的方式,来实现不同的功能选项,尽量避免过多的if判断 40 ''' 41 label = menu.login_register 42 login_reg = menu.login_register_dic 43 flag = False 44 while not flag: 45 print(label) 46 inp = input("请输入编号:").strip() 47 if inp in login_reg: 48 if hasattr(login,login_reg[inp]): 49 func = getattr(login,login_reg[inp]) 50 func() 51 52 else: 53 login_log.error("The input number does not exist, please try again !!!")