Python函数07/有参装饰器/多个装饰器装饰一个函数
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/有参装饰器/多个装饰器装饰一个函数的更多相关文章
- 已知一个函数rand7()能够生成1-7的随机数,请给出一个函数rand10(),该函数能够生成1-10的随机数。
题目: 已知一个函数rand7()能够生成1-7的随机数,请给出一个函数,该函数能够生成1-10的随机数. 思路: 假如已知一个函数能够生成1-49的随机数,那么如何以此生成1-10的随机数呢? 解法 ...
- python进阶04 装饰器、描述器、常用内置装饰器
python进阶04 装饰器.描述器.常用内置装饰器 一.装饰器 作用:能够给现有的函数增加功能 如何给一个现有的函数增加执行计数的功能 首先用类来添加新功能 def fun(): #首先我们定义一个 ...
- Python全栈工程师(函数的传参)
ParisGabriel 感谢 大家的支持 每天坚持 一天一篇 点个订 ...
- Python笔记_第四篇_高阶编程_高阶函数_1.map和reduce
1. map()函数: 原型:map(fn,lsd) 参数1是函数 参数2是序列 功能:将传入的函数一次作用在序列中的每一个元素.并把结果作为一个新的Iterator返回.其实map函数就是一个for ...
- Python定义一个函数
Python函数:实现某种功能的代码段 定义一个函数需要遵循的规则: 1.使用 def 关键字 函数名和( ),括号内可以有形参 匿名函数使用 lambda 关键字定义 2.任何传入参数和自变量必须放 ...
- js中如何在一个函数里面执行另一个函数
1.js中如何在函数a里面执行函数b function a(参数c){ b(); } function b(参数c){ } 方法2: <script type="text/javasc ...
- js new一个函数和直接调用函数的区别
用new和调用一个函数的区别:如果函数返回值是一个值类型(Number.String.Boolen)时,new函数将会返回这个函数的实例对象,而如果这个函数的返回值是一个引用类型(Object.Arr ...
- js new一个函数和直接调用函数的差别
用new和调用一个函数的差别:假设函数返回值是一个值类型(Number.String.Boolen)时,new函数将会返回这个函数的实例对象.而假设这个函数的返回值是一个引用类型(Object.Arr ...
- vue中data必须是一个函数
前端面试时经常被问到:“组建中data为什么是函数”? 答案就是:在组件中data必须是一个函数,这样的话,每个实例可以维护一份被返回对象的独立拷贝.
随机推荐
- Ubuntu18.04美化MacOS(新更grub界面美化)
写在前面的话: 在美化过程中大多数资源来自境外网站,下载时速度特别慢,写这篇博客一是为了给读者看,也是为了自己保存资源并记录ubuntu18.04的使用,避免你们或是自己以后再花费大量时间去百度方法和 ...
- C Primer Plus(三)
重读C Primer Plus ,查漏补缺 重读C Primer Plus,记录遗漏的.未掌握的.不清楚的知识点 文件输入/输出 1.fgets函数在读取文件内容时会将换行符读入,但gets不会,fp ...
- 弹出框Alert
selenium提供了三个处理alert的方法 注意:首先需要切换窗口到alert driver.switch_to.alert() (1)点击确定按钮 driver.switch_to.alert. ...
- Dubbo——服务目录
引言 前面几篇文章分析了Dubbo的核心工作原理,本篇将对之前涉及到但却未细讲的服务目录进行深入分析,在开始之前先结合前面的文章思考下什么是服务目录?它的作用是什么? 正文 概念及作用 清楚Dubbo ...
- SpringBoot 2.0 编程方式配置,不使用默认配置方式
SpringBoot的一般配置是直接使用application.properties或者application.yml,因为SpringBoot会读取.perperties和yml文件来覆盖默认配置: ...
- Spring-AOP:一、注解demo及基本概念
切面:Aspect 切面=切入点+通知.在老的spring版本中通常用xml配置,现在通常是一个类带上@Aspect注解.切面负责将 横切逻辑(通知) 编织 到指定的连接点中. 目标对象:Target ...
- 并发04--JAVA中的锁
1.Lock接口 Lock与Synchronized实现效果一致,通过获得锁.释放锁等操作来控制多个线程访问共享资源,但是Synchronized将获取锁固话,必须先获得锁,再执行,因此两者对比来说, ...
- 01 . Shell详细入门介绍及简单应用
Shell简介 Shell 是一个 C 语言编写的脚本语言,它是用户与 Linux 的桥梁,用户输入命令交给 Shell 解释处理Shell 将相应的操作传递给内核(Kernel),内核把处理的结果输 ...
- ip修改器
哈哈,算法来源于网络... 源码:http://pan.baidu.com/s/11P0P9 参考:http://bbs.csdn.net/topics/370201571 http://bbs.cs ...
- NXP S32V eiq_auto tensorflow offline tool 环境配置
NXP S32V eiq_auto tensorflow offline tool 环境配置 完成cnn模型eiq移植的第一步 1.安装conda 下载.sh bash Anaconda3-5.3.1 ...