模块讲解----反射 (基于web路由的反射)

时间:2022-09-23 22:37:23

一、反射的实际案例:

 def main():
menu = '''
1、账户信息
2、还款
3、取款
4、转账
5、账单
''' menu_dic = {
'':account_info,
'':repay,
'':withdraw,
'':transfer,
'':pay_check,
} while True:
print(menu)
user_option = input(">>: ").strip()
if user_option in menu_dic:
menu_dic[user_option]()

反射的总结

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模块:(模拟不同功能的页面函数)
 '''
根据用户输入的url不同,调用不同的函数。
调用不同的函数,返回不同页面的内容。
''' def login():
print('炫酷登录页面') def logout():
print('炫酷退出页面') def home():
print('炫酷主页面')

2、index模块:(判读用户输入url的不同,返回不同的结果)

 '''
判断用户输入的url的不同,显示不同的结果
''' import commons def run():
inp = input('请输入要访问的url>>>')
if inp == 'login':
commons.login()
elif inp == 'logout':
commons.logout()
elif inp == 'home':
commons.home()
else:
print('') if __name__ == '__main__':
run()
问题:
1、以上是一个网站的三个函数,也是三个页面功能。
2、现实中,一个网站中有多个页面(成百上千个函数),来处理用户的请求。
3、用户访问很多的页面,访问页面越多,那处理访问请求的函数就不一样。
 
解决方法:
1、在commons模块中要定义好多个页面功能函数,这个不变有多少定义多少。
2、在index中,无需多个if判断,只需要将用户输入的input值,自动匹配commons模块里的函数就OK了。
 
修改方法如下:
inp = input(’请输入要访问的url>>> ‘)
 #inp获取到的是字符串类型。 inp = “login”
#commons.inp() != commons.login #回去找inp函数,然后执行
#利用字符串的形式去对象(模块)中,去操作(寻找/检查/删除/设置)成员,反射
getattr(commons,inp)
hasattr(commons,inp)
setattr()
delattr()

反射的使用方法

一、通过反射,寻找/检查模块成员:

 import commons

 def run():
inp = input("请输入要访问的url>>> ") #判断模块中的方法是否存在:
if hasattr(commons,inp): #判读模块内的方法是否存在,如果返回为True则调用。 #获取模块中包含的成员:getattr(模块名,用户输入的url)
func = getattr(commons,inp)
func() else: #如果返回False则打印错误信息 404。
print(404) if __name__ == '__main__':
run()

二、字符串模式的寻找、导入模块:

1、特点:基于web框架的URL路由模式的反射

2、用途:用户输入的url路径转成字符串的格式,然后调用相应的模块名和方法:
例如:account/login
 
3、分析:该需求分为2部分:
第一部分是:将用户输入的url转成字符串。
第二部分是:利用反射的方式通过字符串调用相应的模块和方法:
 def run():
inp = input('请输入要访问的rul>>> ') #获取url
m,f = inp.split('/') #将url转换成字符串
obj = __import__(m) #导入字符串中的模块 if hasattr(obj,f): #用内置函数判断字符串中的函数和方法是否存在,
func = getattr(obj,f) #如果存在,就调用字符串中的模块和方法
func() #执行调用方法 else: #如果不存在则打印404
print(404) if __name__ == '__main__':
run() #本地函数调用 显示结果:
请输入要访问的rul>>> commons/db_mgs
炫酷的数据库连接信息:

三、导入同级文件夹下的模块:

注意:__import__:在默认的时候只导入lib.xx的点前面那个lib模块;
解决方法:需要用字符串拼接("目录名." + 模块名)
                 后参数(fromlist=True)

1、目录结构:

 |day6
--| index.py
-- | lib
--| account.py
--| manager.py
--| 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、定义函数标题:
#登录&注册
login_register = '''
1、登录
2、注册
3、退出
''' login_register_dic = {
'':'acc_login',
'':'acc_auth',
'':'quit'
} #2、定义函数体
def acc_login():
print('this is login') def acc_auth():
print('This is auth') def quit():
print("This is quit") #3、定义反射条件:
from core import logger
from core import login
from core import menu
def run():
'''
被调用的主接口,主要功能如下:
1、展示登录注册信息
2、通过反射的方式,来实现不同的功能选项,尽量避免过多的if判断
'''
label = menu.login_register
login_reg = menu.login_register_dic
flag = False
while not flag:
print(label)
inp = input("请输入编号:").strip()
if inp in login_reg:
if hasattr(login,login_reg[inp]):
func = getattr(login,login_reg[inp])
func() else:
login_log.error("The input number does not exist, please try again !!!")

反射实例