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()

Python函数07/有参装饰器/多个装饰器装饰一个函数的更多相关文章

  1. 已知一个函数rand7()能够生成1-7的随机数,请给出一个函数rand10(),该函数能够生成1-10的随机数。

    题目: 已知一个函数rand7()能够生成1-7的随机数,请给出一个函数,该函数能够生成1-10的随机数. 思路: 假如已知一个函数能够生成1-49的随机数,那么如何以此生成1-10的随机数呢? 解法 ...

  2. python进阶04 装饰器、描述器、常用内置装饰器

    python进阶04 装饰器.描述器.常用内置装饰器 一.装饰器 作用:能够给现有的函数增加功能 如何给一个现有的函数增加执行计数的功能 首先用类来添加新功能 def fun(): #首先我们定义一个 ...

  3. Python全栈工程师(函数的传参)

     ParisGabriel   感谢 大家的支持                                                               每天坚持 一天一篇 点个订 ...

  4. Python笔记_第四篇_高阶编程_高阶函数_1.map和reduce

    1. map()函数: 原型:map(fn,lsd) 参数1是函数 参数2是序列 功能:将传入的函数一次作用在序列中的每一个元素.并把结果作为一个新的Iterator返回.其实map函数就是一个for ...

  5. Python定义一个函数

    Python函数:实现某种功能的代码段 定义一个函数需要遵循的规则: 1.使用 def 关键字 函数名和( ),括号内可以有形参 匿名函数使用 lambda 关键字定义 2.任何传入参数和自变量必须放 ...

  6. js中如何在一个函数里面执行另一个函数

    1.js中如何在函数a里面执行函数b function a(参数c){ b(); } function b(参数c){ } 方法2: <script type="text/javasc ...

  7. js new一个函数和直接调用函数的区别

    用new和调用一个函数的区别:如果函数返回值是一个值类型(Number.String.Boolen)时,new函数将会返回这个函数的实例对象,而如果这个函数的返回值是一个引用类型(Object.Arr ...

  8. js new一个函数和直接调用函数的差别

    用new和调用一个函数的差别:假设函数返回值是一个值类型(Number.String.Boolen)时,new函数将会返回这个函数的实例对象.而假设这个函数的返回值是一个引用类型(Object.Arr ...

  9. vue中data必须是一个函数

    前端面试时经常被问到:“组建中data为什么是函数”? 答案就是:在组件中data必须是一个函数,这样的话,每个实例可以维护一份被返回对象的独立拷贝.

随机推荐

  1. JavaScript 定时器 取消定时器

    感谢:链接(视频讲解很清晰) 定时器:作用主要是一定时间间隔后,做出相关的变化,例如图片轮播. 目录 两种定时器的使用 两种定时器区别 取消定时器的方法 两种定时器的使用: 方法一:setTimeou ...

  2. 将MySQL库的表转入到MSSQL中的某个库中(Employees下的Employees表 → pubs库下)_2

    将MySQL库的表转入到MSSQL中的某个库中(Employees下的Employees表 → pubs库下, 此pubs下的表名是employee,不冲突),方法大致以下几个(另有其他方法待补充), ...

  3. PageHelper支持GreenPlum

    greenplum是pivotal在postgresql的基础上修改的一个数据库,语法和postgresql通用.使用PageHelper做分页插件的时候,发现目前没有针对greenplum做支持,但 ...

  4. 02 . Ansible高级用法(运维开发篇)

    自动化任务简介 假设我们要在10台linux服务器上安装一个nginx服务,手动是如何做的? # 第一步, ssh登录NUM(1,n)服务器 # 第二步,输入对应服务器密码 # 第三步,执行命令: y ...

  5. 【Java】错误: 需要class, interface或enum

    今天在用cmd实现mvn package操作时跳出来的报错! 网上搜索到的结论是因为编码问题而产生的,具体原因就不深究了 要详细了解可以查看以下链接https://blog.csdn.net/qq_3 ...

  6. 面试必问系列之JDK动态代理

    .katex { display: block; text-align: center; white-space: nowrap; } .katex-display > .katex > ...

  7. linux最小化安装命令补全

    bash-completion 需要安装bash-completion才能补全,安装后,重新打开一个窗口就能生效.

  8. 入门大数据---Spark_Streaming整合Kafka

    一.版本说明 Spark 针对 Kafka 的不同版本,提供了两套整合方案:spark-streaming-kafka-0-8 和 spark-streaming-kafka-0-10,其主要区别如下 ...

  9. C++的新手入门答疑

    基本部分: .ctrl+f5 调试不运行,会出现press anykey to continue f5 调试 .c++变c,修改Stdafx.h,将#include<stdio.h>替换为 ...

  10. cp5200的一般步骤

    cp5200的一般步骤: 1.创建数据对象 hObj = CP5200_CommData_Create(nCommType, id, GetIDCode()); 2.生成所需要的数据,如 :生成设置亮 ...