带参数的装饰
应用场景举例:
网站有三个页面,分别是index、home、bbs,原来均不需要认证即可进入;
现需求有变:1)index页面保持原样,无需认证
2)home页面需要通过本地文件认证;
3)bbs需要通过公司LDAP进行认证
由于不希望修改原home()、index()、bbs()的代码,也不希望修改上述三个函数的调用方式和执行结果,决定采用装饰器的方式进行,由于home()和bbs()采用了不同的认证仍是,因此在装饰时需要带入认证方式,具体装饰如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
@auth(auth_type = "local") def home(): print("Welcome to home pages!") return "From Home Page\n" @auth(auth_type = "ldap") def bbs(): print("Welcome to bbs pages!\n")
为了接收装饰中带入的参数,两层嵌套的装饰器函数已经不能满足需求,需要引入三层装饰器函数,具体代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/evn python # -*- coding: utf-8 -*- #Author: Johnson Chen #Function: # 网站有三个页面,分别是index、home、bbs,原来均不需要认证即可进入; # 现需求有变:1)index页面保持原样,无需认证 # 2)home页面需要通过本地文件认证; # 3)bbs需要通过公司LDAP进行认证 username, password = "ccz320","abc123" def ldapAuth(iUsername,iPassword): print("Authencated by LDAP, pass!") return True def auth(auth_type): "装饰器通过引入auth_type方式,运行在装饰的过程中传入认证方式" def outer_wrapper(func): #wrapper()是真正的用于替换被装饰函数的替代品 def wrapper(*args, **kwargs): iUser = input("Username:") iPass = input("Password:") #如果装饰器带入的认证方式是local,则通过本地文件进行认证 if auth_type == "local": if iUser == username and iPass == password: return func(*args, **kwargs) else: exit("\033[41;1mInvalid username or password!\033[0m") #如果装饰器带入的认证方式是ldap,则通过ldapAuth()进行认证 elif auth_type =="ldap": if ldapAuth(iUser, iPass): return func(*args, **kwargs) else: exit("\033[41;1mInvalid username or password!\033[0m") return wrapper return outer_wrapper def index(): print("Welcome to index pages!\n") @auth(auth_type = "local") def home(): print("Welcome to home pages!") return "From Home Page\n" @auth(auth_type = "ldap") def bbs(): print("Welcome to bbs pages!\n") index() print(home()) bbs()
执行结果如下:
Welcome to index pages!
Username:ccz320
Password:abc123
Welcome to home pages!
From Home Page
Username:ccz
Password:123
Authencated by LDAP, pass!
Welcome to bbs pages!