python中的类装饰器应用场景_这是我见过最全面的Python装饰器教程了!
装饰器(Decorators)是 Python 的一个重要部分。简单地说:他们是修改其他函数的功能的函数。他们有助于让我们的代码更简短,也更Pythonic(Python范儿)。在程序开发中经常使用到的功能,合理使用装饰器,能让我们的程序如虎添翼。
1. 函数名应用
函数名是什么?函数名是函数的名字,本质:变量,特殊的变量。
1 ) 函数名就是函数的内存地址,直接打印函数名,就是打印内存地址
def func1():
print(123)
print(func1) #
2 ) 函数名可以作为变量
def func1():
print(111)
f = func1
f() # f() 就是func1()
3 ) 函数名可以作为函数的参数
def func1():
print(111)
def func2(x):
x()
func2(func1) #func1作为func2的参数
4 ) 函数名可以作为函数的返回值
def wrapper():
def inner():
print('inner')
return inner
f = wrapper()
f()
5 ) 函数名可以作为容器类类型的元素
使用for循环批量执行函数
def func1():
print('func1')
def func2():
print('func2')
def func3():
print('func3')
l1 = [func1,func2,func3]
for i in l1:
i()
像上面函数名这种,叫做第一类对象。
第一类对象( first-class object)指:
1.可在运行期创建
2.可用作函数参数或返回值
3.可存入变量的实体
*不明白?那就记住一句话,就当普通变量用
2. 闭包
1、 闭包函数 : 内部函数包含对外部作用域而非全局作用域变量的引用,该内部函数称为闭包函数
2、闭包的作用:爬虫、装饰器
当程序执行遇到函数执行时,会在内存空间开辟局部命名空间,当函数执行完毕,该命名空间会被销毁。但是如果这个函数内部形成闭包,则该内存空间不会随着函数执行完而消失。
3、如何判断是否是闭包:print(函数名.__closure__) 结果是 cell 说明是闭包,结果是 None 说明不是闭包。
闭包举例
def wrapper():
name = 'summer'
def inner():
print(name)
inner()
wrapper() # summer
如何判断它是否是一个闭包函数呢? 内层函数名.__closure__ cell 就是=闭包
例 1.
def wrapper():
name = 'summer'
def inner():
print(name)
inner()
print(inner.__closure__)
wrapper()
执行输出:
summer
(,)
例 2.
name = 'summer'
def wrapper():
def inner():
print(name)
inner()
print(inner.__closure__)
wrapper()
结果输出:
summer
None
返回值为None 表示它不是闭包,因为name是一个全局变量,如果函数调用了外层变量而非全局变量,那么它就是闭包。
例 3.
name = 'summer'
def wrapper2():
name1 = 'spring'
def inner():
print(name)
print(name1)
inner()
print(inner.__closure__)
wrapper2()
结果输出:
summer
spring
(,)
只要引用了外层变量至少一次,非全局的,它就是闭包
例 4:判断 下面的函数,是一个闭包吗? ******
name = 'summer'
def wraaper2(n): #相当于n = 'summer'
def inner():
print(n)
inner()
print(inner.__closure__)
wraaper2(name)
结果输出:
summer
(,)
它也是一个闭包. 虽然wraaper2传了一个全局变量,但是在函数wraaper2内部,inner引用了外层变量,相当于在函数inner外层定义了 n = 'summer',所以inner是一个闭包函数
闭包的好处 : 当函数开始执行时,如果遇到了闭包,他有一个机制,他会永远开辟一个内存空间,将闭包中的变量等值放入其中,不会随着函数的执行完毕而消失。
举一个例子:爬3次,内存开了3次,很占用内存
from urllib.request import urlopen
content1 = urlopen('https://www.cnblogs.com/').read().decode('utf-8')
content2 = urlopen('https://www.cnblogs.com/').read().decode('utf-8')
content3 = urlopen('https://www.cnblogs.com/').read().decode('utf-8')
把它封装成闭包
from urllib.request import urlopen
def index():
url = "https://www.cnblogs.com/"
def get():
return urlopen(url).read()
return get #return的是get,就是一个函数名
cnblog = index()
print(cnblog) # .get at 0x02F46978>
content = cnblog()
print(content) # 页面源码
这个例子,只有第一遍,是从网站抓取的。之后的执行,直接从内存中加载,节省内存空间
3.装饰器
3.1 装饰器初识
装饰器本质: 就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。
装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景。
import time
def timmer(f):
def inner():
start_time = time.time()
f()
end_time = time.time()
print('此函数的执行时间为{}'.format(end_time - start_time))
return inner
def func1():
print('in func1')
time.sleep(1)
func1 = timmer(func1)
print(func1)
func1() # 这里的func1是全新的func1,就是上面的赋值,此时相当于执行 inner函数
输出结果:
.inner at 0x03822DF8>
in func1
此函数的执行时间为1.0003533363342285
代码从上至下执行
语法糖: 想测试谁,前面加@装饰器函数,即可。 写装饰器,约定俗成,函数名为wrapper
def wrapper(func):
def inner(*args,**kwargs):
'''被装饰函数之前'''
ret = func(*args,**kwargs)
'''被装饰函数之后'''
return ret
return inner
@wrapper
def func(*args,**kwargs):
print(args,kwargs)
return 666
print(func())
输出结果:
() {}
666
装饰器利用return制造了一个假象,func()执行,其实是执行inner() , func()把原来的func()给覆盖了
3.2 装饰器传参
例 1: 上面装饰器的例子,func1,要传2个参数a,b
import time
def timmer(f):
def inner(a,b):
start_time = time.time()
f(a,b)
end_time = time.time()
print('此函数的执行时间为{}'.format(end_time - start_time))
return inner
@timmer
def func1(a,b):
print('in func1 {}{}'.format(a,b))
time.sleep(1) # 模拟程序逻辑
func1(1,2)
执行输出:
in func1 12
此函数的执行时间为1.0006024837493896
例 2: 如果有多个参数呢?改成动态参数
import time
def timmer(f):
def inner(*args,**kwargs):
start_time = time.time()
f(*args,**kwargs)
end_time = time.time()
print('此函数的执行时间为{}'.format(end_time - start_time))
return inner
@timmer
def func1(*args,**kwargs):
print('in func1 {}{}'.format(args,kwargs))
time.sleep(1) # 模拟程序逻辑
func1(1,2,a='3',b=4)
执行输出:
in func1 (1, 2){'b': 4, 'a': '3'}
此函数的执行时间为1.000101089477539
函数的执行时,*打散 ;
函数的定义时,*聚合。
from functools import wraps
def wrapper(f): # f = func1
def inner(*args,**kwargs): #聚合,args (1,2,3)
'''执行函数之前的相关操作'''
ret = f(*args,**kwargs) # 打散 1,2,3
'''执行函数之后的相关操作'''
return ret
return inner
@wrapper # func1 = wrapper(func1) func1 = inner
def func1(*args): #args (1,2,3) 聚合
print(666)
return args
print(func1(*[1,2,3]))
执行输出:
666
(1, 2, 3)
例 3 *****
import time #1.加载模块
def timmer(*args,**kwargs): #2.加载变量 5.接收参数True,2,3
def wrapper(f): #6.加载变量 8.f = func1
print(args, kwargs) #9.接收timmer函数的值True,2,3
def inner(*args,**kwargs): #10.加载变量. 13.执行函数inner
if flag: #14 flag = True
start_time = time.time() #15 获取当前时间
ret = f(*args,**kwargs) #16 执行func1
time.sleep(0.3) #19 等待0.3秒
end_time = time.time() #20 获取当前时间
print('此函数的执行效率%f' % (end_time-start_time)) #21 打印差值
else:
ret = f(*args, **kwargs)
return ret #22 返回给函数调用者func1()
return inner #11 返回给函数调用者wrapper
return wrapper #7.返回给函数调用timmer(flag,2,3)
flag = True #3 加载变量
@timmer(flag,2,3) # 4.执行函数timmer(flag,2,3) 17.执行函数func1 两步:1,timmer(flag,2,3) 相当于执行wrapper 2.@wrapper 装饰器 func1 = wrapper(func1)
def func1(*args,**kwargs):
return 666 #18 返回给函数调用者f(*args,**kwargs)
print(func1()) #12 执行函数
写装饰器,一般嵌套3层就可以了
3.3 多个装饰器,装饰一个函数
def wrapper1(func): # func == f函数名
def inner1():
print('wrapper1 ,before func') # 2
func()
print('wrapper1 ,after func') # 4
return inner1
def wrapper2(func): # func == inner1
def inner2():
print('wrapper2 ,before func') # 1
func()
print('wrapper2 ,after func') # 5
return inner2
@wrapper2 # f = wrapper2(f) 里面的f==inner1 外面的f == inner2
@wrapper1 # f = wrapper1(f) 里面的f==函数名f 外面的f == inner1
def f(): # 3
print('in f')
f() # inner2()
执行输出:
wrapper2 ,before func
wrapper1 ,before func
in f
wrapper1 ,after func
wrapper2 ,after func
哪个离函数近,哪个先计算 。 最底下的先执行
执行顺序如下图:
多个装饰器,都是按照上图的顺序来的
4. 装饰器的 __name__ 和 __doc___
__name__:函数名
__doc___:函数的解释
普通函数
def func1():
"""
此函数是完成登陆的功能,参数分别是...作用。
return: 返回值是登陆成功与否(True,False)
"""
print(666)
func1()
print(func1.__name__) #获取函数名
print(func1.__doc__) #获取函数名注释说明
执行输出:
666
func1
此函数是完成登陆的功能,参数分别是...作用。
return: 返回值是登陆成功与否(True,False)
这个有什么用呢?比如日志功能,需要打印出谁在什么时间,调用了什么函数,函数是干啥的,花费了多次时间,这个时候,就需要获取函数的有用信息了
带装饰器的函数
def wrapper(f): # f = func1
def inner(*args,**kwargs): #聚合, args (1,2,3)
'''执行函数之前的相关操作'''
ret = f(*args,**kwargs) # 打散 1,2,3
'''执行函数之后的相关操作'''
return ret
return inner
@wrapper
def func1():
"""
此函数是完成登陆的功能,参数分别是...作用。
return: 返回值是登陆成功与否(True,False)
"""
print(666)
return True
func1()
print(func1.__name__)
print(func1.__doc__)
执行输出:
666
inner
执行函数之前的相关操作
函数装饰之后,相当于执行了inner函数,所以输出inner
为了解决这个问题,需要 调用一个模块wraps
wraps将 被修饰的函数(wrapped) 的一些属性值赋值给修饰器函数(wrapper) ,最终让属性的显示更符合我们的直觉
from functools import wraps
def wrapper(f): # f = func1
@wraps(f) #f是被装饰的函数
def inner(*args,**kwargs): #聚合args (1,2,3)
'''执行函数之前的相关操作'''
ret = f(*args,**kwargs) # 打散 1,2,3
'''执行函数之后的相关操作'''
return ret
return inner
@wrapper
def func1():
"""
此函数是完成登陆的功能,参数分别是...作用。
return: 返回值是登陆成功与否(True,False)
"""
print(666)
return True
func1()
print(func1.__name__)
print(func1.__doc__)
执行输出:
666
func1
此函数是完成登陆的功能,参数分别是...作用。
return: 返回值是登陆成功与否(True,False)
python中的类装饰器应用场景_这是我见过最全面的Python装饰器教程了!相关推荐
- python装饰器作用和功能_这是我见过最全面的Python装饰器详解!没有学不会这种说法!...
今天的任务比较繁重,因为我们要一起来学习Python中比较重要比较牛逼比较难的装饰器. 我将会和大家一起通过代码的形式来迷你银行存款取款的功能,然后通过引入装饰器来一步一步优化代码. 废话不多说梦开始 ...
- 这是我见过最全面的Python装饰器详解!没有学不会这种说法
python装饰器 刚刚接触python的装饰器,简直懵逼了,直接不懂什么意思啊有木有,自己都忘了走了多少遍Debug,查了多少遍资料,才有点点开始明白了. 学习python中有什么不懂的地方,小编这 ...
- 这是我见过最全面的Python装饰器详解 没有学不会这种说法
python装饰器 刚刚接触python的装饰器,简直懵逼了,直接不懂什么意思啊有木有,自己都忘了走了多少遍Debug,查了多少遍资料,才有点点开始明白了. 待会我将会和大家一起通过代码的形式来迷你银 ...
- python装饰器详解-这是我见过最全面的Python装饰器详解!没有学不会这种说法!...
今天的任务比较繁重,因为我们要一起来学习Python中比较重要比较牛逼比较难的装饰器. 我将会和大家一起通过代码的形式来迷你银行存款取款的功能,然后通过引入装饰器来一步一步优化代码. 废话不多说梦开始 ...
- python十大重点_你见过的最全面的 Python 重点
由于总结了太多的东西,所以篇幅有点长,这也是我'缝缝补补'总结了好久的东西. Py2 VS Py3print成为了函数,python2是关键字 不再有unicode对象,默认str就是unicode ...
- python双除号_你见过的最全面的 Python 重点
来源:二十一 链接: https://segmentfault.com/a/1190000018737045 由于总结了太多的东西,所以篇幅有点长,这也是我'缝缝补补'总结了好久的东西. Py2 ...
- python壁纸超清全面屏_你见过的最全面的python重点
首先和大家说个对不起,由于总结了太多的东西,所以篇幅有点长,这也是我"缝缝补补"总结了好久的东西,对于Nginx的东西我没总结在这里,大家可以Python聚焦看,点击直达专栏哦. ...
- 超实用,这是我见过最全面的python入门教程,高中生不要错过
Python 是一门开源免费.通用型的脚本编程语言,它上手简单,功能强大,坚持「极简主义」. Python 类库(模块)极其丰富,这使得 Python 几乎无所不能,不管是传统的 Web 开发.PC ...
- Python中的类、实例以及方法,MRO继承解析顺序以及Mixin类
Contents 1. 什么是类和实例 2. 类的实例方法.类方法和静态方法 3. MRO是什么,描述其查找顺序 4. Mixin是什么,描述其应用场景 5. References 1. 什么是类和实 ...
最新文章
- 代码模拟实现十六进制转二进制
- linux sqlplus 密码有$
- jasmine spyOn的单步调试
- Docker 数据持久化的三种方案
- WeX5 Model 里data ,baasData 数据过滤条件清除 数据初始化
- 如何让service不被系统杀掉
- Shadow Map在DirectX9.0 SDK Sample 的实现方法
- 你还在用 BeanUtils?试试 MapStruct,优雅的对象转换解决方案!
- C#下对象与JSON串互相转换
- win7怎么设置悬浮桌面便签
- 360加固签名验证_360加固助手签名工具怎么用
- 抖音seo,抖音优化系统,抖音seo矩阵系统源码技术搭建
- RabbitMQ笔记
- 数字化医院中智慧医疗的具体应用
- c语言把bit数据合为一个字节,C语言中怎么定义bit型数据
- 信息检索——名词解释、简答题
- Solidity 介绍
- shader实现星空效果
- 【日常问题】API文档的.chm后缀自动生成.chw后缀文件
- SEO建站优化要注意的一些方面