最全面的Python装饰器教程了

装饰器(Decorators)是 Python 的一个重要部分 。简单地说:他们是修改其他函数的功能的函数 。他们有助于让我们的代码更简短,也更Pythonic(Python范儿) 。在程序开发中经常使用到的功能,合理使用装饰器,能让我们的程序如虎添翼 。
私信小编01 获取全套学习教程!
1. 函数名应用
函数名是什么?函数名是函数的名字,本质:变量,特殊的变量 。
1 ) 函数名就是函数的内存地址,直接打印函数名,就是打印内存地址
def func1(): print(123)print(func1)# <function func1 at 0x0000029042E02E18>2 ) 函数名可以作为变量
def func1(): print(111)f = func1f()# f() 就是func1() 3 ) 函数名可以作为函数的参数
def func1(): print(111)def func2(x): x()func2(func1)#func1作为func2的参数 4 ) 函数名可以作为函数的返回值
def wrApper(): def inner(): print('inner') return innerf = 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(<cell at 0x0000017FC9C90B58: str object at 0x0000017FCA349AD0>,)例 2.
name = 'summer'def wrapper(): def inner(): print(name) inner() print(inner.__closure__)wrapper() 结果输出:summerNone返回值为None 表示它不是闭包,因为name是一个全局变量,如果函数调用了外层变量而非全局变量,那么它就是闭包 。
例 3.
name = 'summer'def wrapper2(): name1 = 'spring' def inner(): print(name) print(name1) inner() print(inner.__closure__)wrapper2()结果输出:summerspring(<cell at 0x030B7310: str object at 0x03043680>,)只要引用了外层变量至少一次,非全局的,它就是闭包
例 4:判断 下面的函数,是一个闭包吗? ******
name = 'summer'def wraaper2(n):#相当于n = 'summer'def inner(): print(n) inner() print(inner.__closure__) wraaper2(name)结果输出:summer(<cell at 0x03867350: str object at 0x037F3680>,)它也是一个闭包. 虽然wraaper2传了一个全局变量,但是在函数wraaper2内部,inner引用了外层变量,相当于在函数inner外层定义了 n = 'summer',所以inner是一个闭包函数
闭包的好处 : 当函数开始执行时,如果遇到了闭包,他有一个机制,他会永远开辟一个内存空间,将闭包中的变量等值放入其中,不会随着函数的执行完毕而消失 。
举一个例子:爬3次,内存开了3次,很占用内存
from urllib.request import urlopencontent1 = 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 urlopendef index(): url = "https://www.cnblogs.com/" def get(): return urlopen(url).read() return get#return的是get,就是一个函数名cnblog = index()print(cnblog) # <function index.<locals>.get at 0x02F46978>content = cnblog()print(content) # 页面源码这个例子,只有第一遍,是从网站抓取的 。之后的执行,直接从内存中加载,节省内存空间
3.装饰器
3.1 装饰器初识
装饰器本质: 就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象 。


推荐阅读