百万年薪python之路 -- 装饰器
装饰器
1.1 开放封闭原则
开放封闭原则具体定义是这样:
1.对扩展是开放的
我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。
2.对修改是封闭的
因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对函数内部进行修改,或者修改了函数的调用方式,很有可能影响其他已经在使用该函数的用户。
定义:在不改变原被装饰的函数的源代码以及调用方式下,为其添加额外的功能。
实现真正的开放封闭原则:装饰器。
运用闭包原理:
import time
def index():
time.sleep(2) # 模拟一下网络延迟以及代码的效率
print('这是一个主页')
def access_index(name):
time.sleep(3) # 模拟一下网络延迟以及代码的效率
print(f'欢迎访问{name}主页')
套一层最外面的函数timer,然后将里面的inner函数名作为最外面的函数的返回值
def timer(func): # func = index
def inner():
start_time = time.time()
func()
end_time = time.time()
print(f'此函数的执行效率为{end_time-start_time}')
return inner
# f = timer(index)
# f()
我们分析一下代码,代码执行到这一行:f = timer(index) 先执行谁?看见一个等号先要执行等号右边, timer(index) 执行timer函数将index函数名传给了func形参。内层函数inner执行么?不执行,inner函数返回 给f变量。所以我们执行f() 就相当于执行inner闭包函数。 f(),这样既测试效率又执行了原函数,有没有问题?当然有啦!!我们要解决原函数执行方式不改变的问题,怎么做? 所以你可以把 f 换成 index变量就完美了! index = timer(index) 特别要注意 函数外面的index实际是inner函数的内存地址而不是index函数。这个timer就是最简单版本装饰器,在不改变原index函数的源码以及调用方式前提下,为其增加了额外的功能,测试执行效率。
1.2标准版装饰器
def wrapper(func):
def inner(*args,**kwargs):
'''执行被装饰函数之前的操作'''
ret = func(*args,**kwargs)
'''执行被装饰函数之后的操作'''
return ret
return inner
import time
def wrapper(f):
def inner(*args,**kwargs):
start = time.time() #调用函数之前的操作
f(*args,**kwargs)
end = time.time()
print(end - start) #调用函数之后的操作
return inner
def func(*args,**kwargs):
time.sleep(0.5)
print(f"{args[0]}暴打{args[1]}页面!")
func = wrapper(func)
func("章超印","煞笔周道镕")
语法糖:@xxx
import time
def wrapper(f):
def inner(*args,**kwargs):
start = time.time() #调用函数之前的操作
f(*args,**kwargs)
end = time.time()
print(end - start) #调用函数之后的操作
return inner
@wapper # 等于 func = wapper(func)
def func(*args,**kwargs):
time.sleep(0.5)
print(f"{args[0]}暴打{args[1]}页面!")
# func = wapper(func)
func("章超印","煞笔周道镕")
带参数的装饰器:
在装饰器的基础上再套一层
你现在要完成的就是你的装饰器要分情况去判断账号和密码,不同的函数用的账号和密码来源不同。 但是你之前写的装饰器只能接受一个参数就是函数名,所以你写一个可以接受参数的装饰器。
dic = {
"flag":False,
"username":None
}
msg ="""
QQ
微信
抖音
邮箱
>>>
"""
choose = input(msg).upper()
def auth(argv):
def wrapper(func):
def inner(*args, **kwargs):
if dic["flag"]:
foo(*args, **kwargs)
else:
if argv == "QQ":
print("欢迎来到QQ!")
user = input("username:")
pwd = input("password:")
if user == "zcy1" and pwd == "123":
dic["flag"] = True
dic["username"] = user
elif argv == "微信":
print("欢迎来到微信!")
user = input("username:")
pwd = input("password:")
if user == "zcy2" and pwd == "1234":
dic["flag"] = True
dic["username"] = user
elif argv == "抖音":
print("欢迎来到抖音!")
user = input("username:")
pwd = input("password:")
if user == "zcy3" and pwd == "12345":
dic["flag"] = True
dic["username"] = user
else:
print("欢迎来到邮箱!")
user = input("username:")
pwd = input("password:")
if user == "zcy4" and pwd == "123456":
dic["flag"] = True
dic["username"] = user
ret = func(*args, **kwargs)
return ret
return inner
return wrapper
@auth(choose)
# wrapper = auth(choose)
# foo = wrapper()
def foo():
return "我不管,章超印超帅!"
# @auth(choose) 等于下面的两行
# wrapper = auth(choose)
# foo = wrapper()
print(foo())
@auth('choose') :分两步:
第一步先执行auth('choose')函数,得到返回值wrapper
第二步@与wrapper结合,形成装饰器@wrapper然后在依次执行。
这样就是带参数的装饰器,参数可以传入多个
2.多个装饰器装饰一个函数
被装饰的函数正上方有多个装饰器,先执行离被装饰函数最近的装饰器
我们现在知道标准装饰器和带参数的装饰器,我们来看看多个装饰器装饰一个函数:
def wrapper1(func):
def inner1(*args,**kwargs):
print("这是装饰器一开始")
func(*args,**kwargs)
print("这是装饰器一结束")
return inner1
def wrapper2(func):
def inner2(*args,**kwargs):
print("这是装饰器二开始")
func(*args,**kwargs)
print("这是装饰器二结束")
return inner2
@wrapper1
@wrapper2
def func():
print("这是被装饰的函数")
func()

大家来推断一下,这个的打印结果
这是装饰器一开始
这是装饰器二开始
这是被装饰的函数
这是装饰器二结束
这是装饰器一结束
先执行离被装饰的函数最近的语法糖
# 小技巧:进入装饰器从上往下,走到最会一个装饰器执行被装饰的函数,退出装饰器从下往上走
百万年薪python之路 -- 装饰器的更多相关文章
- 百万年薪python之路 -- 装饰器进阶
本文链接:https://blog.csdn.net/xiemanR/article/details/72510885 一:函数装饰函数 def wrapFun(func): def inner(a, ...
- python之路--装饰器
二 .通用装饰器的写法 python里面的动态代理. 存在的意义: 在不破坏原有的函数和原有函数的调用基础上,给函数添加新的功能 def wrapper(fn): # fn是目标函数. def inn ...
- python之路——装饰器函数
阅读目录 楔子 装饰器的形成过程 开放封闭原则 谈装饰器主要功能和装饰器固定结构 带参数的装饰器 多个装饰器装饰一个函数 返回顶部 楔子 作为一个会写函数的python开发,我们从今天开始要去公司上班 ...
- 百万年薪python之路 -- 面向对象之所有属性及方法
1.私有成员公有成员 1.1 类的私有属性 # class A: # # name = '周道镕' # __name = 'zdr' # 私有类的属性 # # def func(self): # pr ...
- 百万年薪python之路 -- 软件的开发规范
一. 软件的开发规范 什么是开发规范?为什么要有开发规范呢? 你现在包括之前写的一些程序,所谓的'项目',都是在一个py文件下完成的,代码量撑死也就几百行,你认为没问题,挺好.但是真正的后端开发的项目 ...
- python之路---装饰器函数
阅读目录 楔子 装饰器的形成过程 开放封闭原则 谈装饰器主要功能和装饰器固定结构 带参数的装饰器 多个装饰器装饰一个函数 返回顶部 楔子 作为一个会写函数的python开发,我们从今天开始要去公司上班 ...
- 百万年薪python之路 -- 闭包
2.闭包 闭包的定义: 闭包是嵌套在函数中的函数. 闭包必须是内层函数对外层函数的变量(非全局变量)的引用. 一句话定义就是:在嵌套函数内,对非全局变量 (且不是本层的变量)的引用 如何判断判断闭包? ...
- 百万年薪python之路 -- 前端CSS样式
CSS样式 控制高度和宽度 width宽度 height高度 块级标签能设置高度和宽度,而内联标签不能设置高度和宽度,内联标签的高度宽度由标签内部的内容来决定. 示例: <!DOCTYPE ht ...
- 百万年薪python之路 -- 面向对象之 反射,双下方法
面向对象之 反射,双下方法 1. 反射 计算机科学领域主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省) python面向对象中的反射:通过字符串的形式操作对象相关的属性.python ...
随机推荐
- [Leetcode][动态规划] 零钱兑换
一.题目描述 给定不同面额的硬币 coins 和一个总金额 amount.编写一个函数来计算可以凑成总金额所需的最少的硬币个数.如果没有任何一种硬币组合能组成总金额,返回 -1. 示例 1: 输入: ...
- AppScan工具使用-实战一
本文首发于简书https://www.jianshu.com/p/639cf894838e 工具已经安装完成,废话不多说,直接拿手上的项目使用一下. 1.打开工具,点击文件-新建 2.打开新建扫描 3 ...
- python9
v> 软件测试 广州博才科技开发有限公司 迅捷PDF编辑器 3.5 集合 学习目标: 1. 能够说出如何创建集合 2. 能够说出字典和集合的区别 3. 能够说出如何向集合中添加元素 4. 能够说 ...
- setInterval、setTimeout之遗忘的第三个参数
今天看阮一峰老师的ES6入门,在一个关于promise的小demo里,老师用到了setTimeout的第三个参数,惊了有没有,定时器还有第三个参数? 喏就是下面这个demo: function tim ...
- 站内搜索(ELK)之数据表字典类型字段的索引思路
数据表字典类型的字段,如人员表中的“性别”.流程表中的“处理状态”,此类字段中的值高度重复,不建议放到可检索的索引字段中,原因如下: 若数据表字典类型字段的值索引到单独的索引字段中,因字典数据字符数一 ...
- Save&Load--Unity存档读档的学习总结
存档与读档功能 举例: 传统RPG游戏(仙剑.空之轨迹): 1.角色信息(生命值,等级) 2.道具信息(装备,药品) 3.场景信息(场景名称.角色坐标) 4.事件信息(任务相关) 关卡类游戏:关卡的通 ...
- HttpWebRequest上传多文件和多参数——整理
1.整理HttpWebRequest上传多文件和多参数.较上一个版本,更具普适性和简易型.注意(服务方web.config中要配置)这样就可以上传大文件了 <system.webServer&g ...
- 【网络安全】给你讲清楚什么是XSS攻击
给你讲清楚什么是XSS攻击 1. 什么是XSS攻击 跨站脚本攻击(Cross Site Scripting)本来的缩写为CSS,为了与层叠样式表(Cascading Style Sheets,CSS) ...
- iOS开发进阶(唐巧)读书笔记(一)
如何提高iOS开发技能 1.阅读博客:https://github.com/tangqiaoboy/iOSBlogCN 40多位iOS开发博主的博客地址 2.读书:每年阅读一本高质量的iOS开发书籍 ...
- php7和php5区别是什么
PHP7距正式发布以及有挺长时间了,刚出道就号称比旧版本快了几倍,各种开源框架或系统运行在PHP7上速度效率提高了几倍.那么php7和php5之间的区别是什么?下面本篇文章就来给大家简单介绍一下,希望 ...