Python函数07/有参装饰器/多个装饰器装饰一个函数
内容大纲
1.有参装饰器
2.多个装饰器装饰一个函数
1.有参装饰器
# def auth(argv):
# def wrapper(func):
# def inner(*args,**kwargs):
# func(*args,**kwargs)
# return inner
# return wrapper
# login_dic = {
# "username": None,
# "flag": False
# }
# def auth(argv): # argv == foo
# def wrapper(func):
# def inner(*args,**kwargs):
# if login_dic["flag"]:
# func(*args,**kwargs)
# else:
# if argv == "QQ":
# user = input("username:")
# pwd = input("password:")
# if user == "alex" and pwd == "alex123": # qq
# login_dic["flag"] = True
# login_dic["username"] = user
# func(*args,**kwargs)
# else:
# print("用户名或密码错误!")
# elif argv == "微信":
# user = input("username:")
# pwd = input("password:")
# if user == "1351101501" and pwd == "alex": # 微信
# login_dic["flag"] = True
# login_dic["username"] = user
# func(*args, **kwargs)
# else:
# print("用户名或密码错误!")
# elif argv == "抖音":
# user = input("username:")
# pwd = input("password:")
# if user == "alexdsb" and pwd == "alex": # 抖音
# login_dic["flag"] = True
# login_dic["username"] = user
# func(*args, **kwargs)
# else:
# print("用户名或密码错误!")
# else:
# user = input("username:")
# pwd = input("password:")
# if user == "alexdsb@dsb.com" and pwd == "alex": # 邮箱
# login_dic["flag"] = True
# login_dic["username"] = user
# func(*args, **kwargs)
# else:
# print("用户名或密码错误!")
#
# return inner
# return wrapper
#
# # 错误的案例
# @auth # foo = auth(foo)
# def foo():
# print("这是一个被装饰的函数")
#
# foo()
login_dic = {
"username": None,
"flag": False
}
# 正确的案例
msg = """
QQ
微信
抖音
邮箱
请输入您要选择登陆的app:
"""
chose = input(msg).upper()
def auth(argv):
def wrapper(func):
def inner(*args,**kwargs):
if login_dic["flag"]:
func(*args,**kwargs)
else:
if argv == "QQ":
print("欢迎登陆QQ")
user = input("username:")
pwd = input("password:")
if user == "alex" and pwd == "alex123": # qq
login_dic["flag"] = True
login_dic["username"] = user
func(*args,**kwargs)
else:
print("用户名或密码错误!")
elif argv == "微信":
print("欢迎登陆微信")
user = input("username:")
pwd = input("password:")
if user == "1351101501" and pwd == "alex": # 微信
login_dic["flag"] = True
login_dic["username"] = user
func(*args, **kwargs)
else:
print("用户名或密码错误!")
elif argv == "抖音":
print("来了,老弟!")
user = input("username:")
pwd = input("password:")
if user == "alexdsb" and pwd == "alex": # 抖音
login_dic["flag"] = True
login_dic["username"] = user
func(*args, **kwargs)
else:
print("用户名或密码错误!")
else:
print("欢迎登陆dab邮箱")
user = input("username:")
pwd = input("password:")
if user == "alexdsb@dsb.com" and pwd == "alex": # 邮箱
login_dic["flag"] = True
login_dic["username"] = user
func(*args, **kwargs)
else:
print("用户名或密码错误!")
return inner
return wrapper
@auth("QQ")
def foo():
print("这是一个被装饰的函数")
# wrapper = auth(chose)
# foo = wrapper(foo)
foo()
"""
# @auth(chose) 相等于以下两行代码的解构
# wrapper = auth(chose)
# foo = wrapper(foo)
"""
2.多个装饰器装饰一个函数
def wrapper1(func):
def inner1(*args,**kwargs):
print(1)
func(*args,**kwargs)
print(11)
return inner1
def wrapper2(func): # func == foo
def inner2(*args,**kwargs):
print(11)
func(*args, **kwargs)
print(22)
return inner2
def wrapper3(func):
def inner3(*args,**kwargs):
print(3)
func(*args, **kwargs)
print(33)
return inner3
# @wrapper1 # 1 11
# @wrapper3 # 3 33
# @wrapper2 # 8 22
# def foo():
# print(8)
# foo = wrapper2(foo) # foo == inner2
# foo = wrapper3(foo) # inner3 = wrapper3(inner2)
# foo = wrapper1(foo) # inner1 = wrapper1(inner3)
# foo() # inner1()
# foo = wrapper3(foo) # foo == inner3
# foo = wrapper2(foo) # foo = wrapper2(inner3) foo == inner2
# foo = wrapper1(foo) # foo = wrapper1(inner2)
被装饰的函数正上方有多个装饰器,先执行离被装饰函数最近的装饰器
3.今日总结
# 1.有参装饰器
# 在装饰器的基础上再套一层
# @auth("QQ")
# def foo():
# pass
# f = auth("qq")
# foo = f(foo)
# foo()
# 2.多个装饰器装饰一个函数
# def wrapper1(func):
# def inner1(*args,**kwargs):
# print(1)
# func(*args,**kwargs)
# print(11)
# return inner1
#
# def wrapper2(func): # func == foo
# def inner2(*args,**kwargs):
# func(*args, **kwargs)
# print(22)
# return inner2
#
# def wrapper3(func):
# def inner3(*args,**kwargs):
# print(3)
# func(*args, **kwargs)
# print(33)
# return inner3
# @wrapper1 # 1 11
# @wrapper3 # 3 33
# @wrapper2 # 8 22
# def foo():
# print(8)
先执行离被装饰的函数最近的语法糖
小技巧:进入装饰器从上往下,走到最会一个装饰器执行被装饰的函数,退出装饰器从下往上走
3.今日练习
1.请实现一个装饰器,限制该函数被调用的频率,如10秒一次(面试题)
# import time
# def wrapper(f):
# t = 0
# def inner(*args,**kwargs):
# nonlocal t
# if time.time()-t >= 10:
# t = time.time()
# f(*args,**kwargs)
# else:
# print("被限制了")
# return inner
# @wrapper
# def func():
# print("被装饰函数")
# while True:
# func()
# time.sleep(2)
# func()
# time.sleep(2)
# func()
# time.sleep(2)
#
# 2.请写出下列代码片段的输出结果:
# def say_hi(func):
# def wrapper(*args,**kwargs):
# print("HI")
# ret=func(*args,**kwargs)
# print("BYE")
# return ret
# return wrapper
#
# def say_yo(func):
# def wrapper(*args,**kwargs):
# print("Yo")
# return func(*args,**kwargs)
# return wrapper
# @say_hi
# @say_yo
# def func():
# print("ROCK&ROLL")
# func()
# HI
# Yo
# ROCK&ROLL
# BYE
#
3.编写装饰器完成下列需求:
# 用户有两套账号密码,一套为京东账号密码,一套为淘宝账号密码分别保存在两个文件中。
# 设置四个函数,分别代表 京东首页,京东超市,淘宝首页,淘宝超市。
# 启动程序后,呈现用户的选项为:
# 1,京东首页
# 2,京东超市
# 3,淘宝首页
# 4,淘宝超市
# 5,退出程序
# 四个函数都加上认证功能,用户可任意选择,用户选择京东超市或者京东首页,只要输入一次京东账号和密码并成功,
# 则这两个函数都可以任意访问;用户选择淘宝超市或者淘宝首页,只要输入一次淘宝账号和密码并成功,则这两个函数都可以任意访问.
# 相关提示:用带参数的装饰器。装饰器内部加入判断,验证不同的账户密码。
# msg = """
# 1,京东首页
# 2,京东超市
# 3,淘宝首页
# 4,淘宝超市
# 5,退出程序
# 请选择序号>>>:
# """
# login_dic = {
# "jd":False,
# "tb":False
# }
# def auth(argv):
# def wrapper(f):
# def inner(*args,**kwargs):
# if login_dic[argv]:
# f(*args,**kwargs)
# else:
# print(f"{argv} login")
# user = input("请输入姓名:")
# psd = input("请输入密码:")
# with open(argv,"r",encoding="utf-8") as f1:
# for i in f1:
# username,password = i.strip().split(":")
# if user == username and psd == password:
# login_dic[argv] = True
# print("登录成功!")
# return f(*args,**kwargs)
# else:
# print("账号或密码错误")
# return inner()
# return inner
# return wrapper
#
# @auth("jd")
# def jd_index():
# print("这是京东主页")
#
# @auth("jd")
# def jd_shopping():
# print("这是京东超市")
#
# @auth("tb")
# def tb_index():
# print("这是淘宝主页")
#
# @auth("tb")
# def tb_shopping():
# print("这是淘宝超市")
#
# dic = {"1":jd_index ,"2":jd_shopping ,"3":tb_index,"4":tb_shopping, "5":exit}
# while True:
# choose = input(msg)
# if choose in dic:
# dic[choose]()
# else:
# print("请正确输入")
#
4.给l1 = [1,1,2,2,3,3,6,6,5,5,2,2]去重,不能使用set集合(面试题)。
# l1 = [1,1,2,2,3,3,6,6,5,5,2,2]
# lst = []
# for i in l1:
# if i not in lst:
# lst.append(i)
# print(lst)
#
5.用递归函数完成斐波那契数列(面试题):
# 斐波那契数列:1,1,2,3,5,8,13,21..........(第三个数为前两个数的和,但是最开始的1,1是特殊情况,可以单独讨论)
# lst = []
# def func(num):
# if num == 0:
# ret = 1
# elif num == 1:
# ret =1
# else:
# ret = (func(num-2)+func(num-1))
# return ret
# num = int(input(">>>"))
# n = 0
# while func(n) < num:
# lst.append(func(n))
# n += 1
# print(lst)
6.用户输入序号获取对应的斐波那契数字:比如输入6,返回的结果为8.
# def func(num):
# if num == 0:
# ret = 1
# elif num == 1:
# ret =1
# else:
# ret = (func(num-2)+func(num-1))
# return ret
# print(func(5))
7.请实现一个装饰器,限制该函数被调用的频率,如10秒一次(面试题)
# import time
# def wrapper(f):
# t = 0
# def inner(*args,**kwargs):
# nonlocal t
# if time.time()-t >= 10:
# t = time.time()
# f()
# else:
# print("被限制了")
# return inner
# @wrapper
# def func():
# print("被装饰函数")
# func()