python安装教程(2020最新)(这是我见过最全面的Python装饰器教程了!)python教程 / python装饰器与生成器教程...

wufei123 发布于 2024-06-25 阅读(3)

装饰器(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) # 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函数 输出结果: in func1 此函数的执行时间为1.0003533363342285 。

代码从上至下执行语法糖: 想测试谁,前面加@装饰器函数,即可 写装饰器,约定俗成,函数名为wrapperdef 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)

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

河南中青旅行社综合资讯 奇遇综合资讯 盛世蓟州综合资讯 综合资讯 游戏百科综合资讯 新闻15258