一、什么是闭包函数?
在听了Egon老师的讲解后我有了一些见解来跟xdm分享:
闭包函数=名字空间与作用域+函数嵌套+函数对象 ‘闭'函数指的该函数是内嵌函数 ‘包’函数指的该函数包含对外层函数作用域名字的引用(不是对全局作用域)
注意:内部函数包含对外部作用域而非全局作用域的引用
来为大家举个例子:
x=100
def f1():
x=1
def f2():
print(x)
return f2
# 可以理解为f2就是被f1包起来的函数,它的内容(如x)是外层函数f1(x=1)所提供而非全局的作用域(x-100)所提供
f=f1()# ==》f=f1的return=》f=f2==》得到的是f2的内存地址
print(f)# ==><function f1.<locals>.f2 at 0x0000022DA470D3A0>
f()#==》f2()==>1
二、无参装饰器
首先大家要明白装饰器就是闭包函数的一种应用场景
那xdm知道-为何要用装饰器吗?
根据开放封闭原则:对修改封闭,对扩展开放
有时大家在做项目时,你写好了一个功能,当你想要为这个功能添加或修改一些功能时,如果不用装饰器,你可能要在原来的功能代码上进行修改,要是每次都要在原来的代码上进行修改,大家会不会觉得太累了呢?特别是你要在别人写的功能代码上进行修改时。而装饰器遵循的开放封闭原则很好的避免了这个问题。
什么是装饰器?
装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。
强调装饰器的原则:
1 不修改被装饰对象的源代码
2 不修改被装饰对象的调用方式
装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能
首先我来跟大家列下无参装饰器的模板:
# 无参装饰器模板
'''def 无参装饰器(func):
def wrapper(*args,**kwargs):
res=func(*args,**kwargs)
return res
return wrapper
@无参装饰器
def 被装饰函数():
...
'''
下面我们来用无参装饰器的模板来进行一个小的案例:
import time
def timmer(func):
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
stop = time.time()
print(stop - start)
return res
return wrapper
# 上面者段代码的功能就是计算传进来的函数func运行所需的时间
# 当运行到@装饰器时,不会去运行装饰器下面的函数,调用的是装饰器的函数功能
@timmer#==>index=tmmer(index)
def index(x,y):
time.sleep(2)
print('index %s %s'%(x,y))
return x+y
index(2,3)
# 输出结果为:
# index 2 3
# 2.006439685821533
这就是套用的无参装饰器的模板,但大家想必也很疑惑和好奇,它的原理是什么,下面我将不用装饰器,来实现上面一样的功能和输出结果
def index(x,y):
time.sleep(2)
print('index %s %s'%(x,y))
return x+y
def outter(func):
def wrapper(*args,**kwargs):
start=time.time()
res=func(*args,**kwargs)
stop=time.time()
print(stop-start)
return res
return wrapper
index=outter(index)
# 将index函数作为参数传入outter(func)
# ==》将outter的返回值传给变量index(注意区分,第一个index和第二个index)
# ==》index=wrapper==》index指向的是wrapper的内存地址而非index函数的内存地址
index(2,3)# ==》其实运行的是wrapper(2,3)
# start=time.time() 记录运行func()开始前的时间
# res=func(*args,**kwargs)==>res=index(2,3)==>index是传进来的参数,(2,3)是wrapper(2,3)的参数
# stop=time.time() 记录func()结束后的时间
# print(stop-start)打印时间差即函数运行的时间
# return res 返回调用index()return的结果 ,若没有return 则默认为None
print('====>',index(2,5))
想必大家应该也明白了其中的原理,有参的装饰器运行的原理也和上面的无参装饰器的原理差不多。当有多个装饰器装饰一个函数时,从最下面的装饰器开始调用
def outter1(func1): #func1=wrapper2的内存地址
print('加载了outter1')
def wrapper1(*args,**kwargs):
print('执行了wrapper1')
res1=func1(*args,**kwargs)
return res1
return wrapper1
def outter2(func2): #func2=wrapper3的内存地址
print('加载了outter2')
def wrapper2(*args,**kwargs):
print('执行了wrapper2')
res2=func2(*args,**kwargs)
return res2
return wrapper2
def outter3(func3): # func3=最原始的那个index的内存地址
print('加载了outter3')
def wrapper3(*args,**kwargs):
print('执行了wrapper3')
res3=func3(*args,**kwargs)
return res3
return wrapper3
@outter1 # outter1(wrapper2的内存地址)======>index=wrapper1的内存地址
@outter2 # outter2(wrapper3的内存地址)======>wrapper2的内存地址
@outter3 # outter3(最原始的那个index的内存地址)===>wrapper3的内存地址
def index():
print('from index')
print('======================================================')
index()
# 输出结过如下:
’‘’
加载了outter3
加载了outter2
加载了outter1
======================================================
执行了wrapper1
执行了wrapper2
执行了wrapper3
from index
‘’‘
三、有参装饰器
有参装饰器模板
'''def 有参装饰器(参数):
def outter(func):
def wrapper(*args,**kwargs):
res=func(*args,**kwargs)
return res
return wrapper
return outter
@有参装饰器(参数)
def 被装饰函数():
...
'''
原理无非和无参装饰器一样,就不为大家详细介绍啦,有兴趣的兄弟可以课下自己套用模板试一下,不会的可以私信我欧,希望大家喜欢,一起进步!要是喜欢的话欢迎大家来关注我欧~有不足的地方欢迎大家指出,会继续为xdm更新的