装饰器有非常强大的功能,可以不修改函数源代码和调用方式,就给函数加上了对应想要的功能,简直就是 修饰函数的利器。 上一篇文章:初学者python笔记(装饰器、高阶函数、闭包)已经非常详细的剖析了装饰器的原理,本篇就来实现就来具体实现一个登陆验证的案例(源码可以直接使用)
被修饰的函数参数个数是不固定的,而要修改参数个数就肯定需要修改装饰器和原函数,违反了装饰器的修改原函数源代码的原则。
而基本装饰器本来是不带有参数的,如果调用原函数需要传入参数怎么办?可以如下操作:
#装饰器
import time
def timmer(func):
def wrap(*args,**kwargs):
#一个接收列表,一个接收字典,用容器作为参数就可以不限参数个数了
#相当于:foo('夏洛特玲玲','50','female','拿破仑','卡塔库栗'),
#args=['夏洛特玲玲','50','female','拿破仑','卡塔库栗'],kwargs={ }
start_time = time.time() #给装饰器加的功能
res = func(*args,**kwargs) #在装饰器中运行函数,并且用一个变量来接收以返回原函数的返回值
stop_time = time.time()
print('函数运行了{}秒'.format(stop_time - start_time))
return res #返回原函数的返回值
return wrap #函数的返回值是函数,所以为高阶函数
#原函数
@timmer #语法糖的使用,使原函数即foo函数被装饰。相当于foo = timmer(foo)语句
def foo(name,age,sex,weapen,son):
time.sleep(3)
print('test函数运行完毕!\n名字:%s,年龄:%s, 性别:%s,武器:%s,儿子:%s' %(name,age,sex,weapen,son))
return '这是test的返回值' #为了实现把原函数的返回值也接收到
#调用被修饰后的原函数
foo('夏洛特玲玲','50','female','拿破仑','卡塔库栗') #运行原函数,方式不变,满足原则
#可以看到,加了*args和*kargs后就无论多少个参数都能正常运行了
运行结果:
test函数运行完毕!
名字:夏洛特玲玲,年龄:50, 性别:female,武器:拿破仑,儿子:卡塔库栗
函数运行了3.0121726989746094秒
user_list = [ #查询密码的列表,包含所有的账号密码
{'name':'路飞','passwd':'1111'}, #重点知识:因为你输入的是字符串,
{'name':'索隆','passwd':'2222'}, #所以你字典的value也必须是字符串格式,不能是数字格式的值
{'name':'罗','passwd':'3333'},
{'name':'基德','passwd':'4444'}
]
current_dic = {'username':None ,'login':False} #记录当前用户登陆状态的字典
#带验证功能的装饰器
def auth_func(func):
def wrapper(*args, **kwargs):
if current_dic['username'] and current_dic['login']:
#如果都为True就执行,即输入过账号密码后就不需要再次输入了
res = func(*args, **kwargs) #直接执行,不需要再输入账号密码
return res
#否则就输入账号密码
username = input('用户名:').strip() #让用户输入登陆信息
passwd = input('密码:').strip()
#遍历字典来匹配账号密码是否正确
for user_dic in user_list: #user_dic是用来遍历列表中每个字典的变量
#print(user_dic['name'],user_dic['passwd'])
if user_dic['name'] == username and user_dic['passwd'] == passwd: #验证账号密码
#print(user_dic['name'],user_dic['passwd'])
#输入正确就记录下登陆状态,用记录状态的字典
current_dic['username'] = username
current_dic['login'] = True
#print(current_dic['login'])
res = func(*args, **kwargs) #接收原函数返回值
return res
#else跟for成对,表明如果你输入的连用户名都不存在,那就不用遍历了
else:
print('用户名或密码错误!!!')
return wrapper #如果密码错误就不会有返回值,而是返回wrapper重新再输入
@auth_func
def index():
print('欢迎来到淘宝主页!')
@auth_func
def home(name):
print('欢迎%s回家' %name)
@auth_func
def shopping_car(name):
print('%s的购物车里有:%s、%s、%s' %(name,'连衣裙','海贼手办','迪迦凹凸曼'))
print('初始用户状态:',current_dic)
index()
print('输入后用户状态:',current_dic)
home('您') #该函数无论传入什么值都可以,只是给函数内部多一个全局变量
shopping_car('您')
运行结果:
初始用户状态: {‘username’: None, ‘login’: False}
用户名:索隆
密码:2222
欢迎来到淘宝主页!
输入后用户状态: {‘username’: ‘索隆’, ‘login’: True}
欢迎您回家
您的购物车里有:连衣裙、海贼手办、迪迦凹凸曼
以上就是装饰器案例的实现,如果你看了上一篇装饰器原理的文章,本篇案例肯定是可以理解的