首先我们应该知道一件事:函数的定义域跟定义位置有关系,而跟调用位置没有关系。
闭包函数:
定义:内层函数对外层函数而非全局变量的引用,就叫做闭包函数
闭包会一直存在在内存中,不会因为函数执行结束而被释放
先看个例子:
def outer():
num = 1
def inner():
nonlocal num
num += 1
print(num)
return inner
a = outer() # 此时a为一个函数
a() # 2
a() # 3
a() # 4
num会一直存在,不会因为外层函数结束而释放。
这就是闭包函数,可以在任何地方调用
闭包的意义
意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,
这使得无论在何处调用,优先使用自己外层包裹的作用域
装饰器:闭包函数的一种应用场景
装饰器原则:1,不修改对象的源代码,2,不修改对象的调用方式,
目标:在遵循1,2的前提下,为被装饰对象添加上新的功能
假如我们有这样一个需求,测试一个函数所用的时间
import time
def function():
time.sleep(1)
print('函数执行')
start_time = time.time()
function()
end_time = time.time()
print("函数的执行时间%s" %(end_time - start_time))
# 但此时多了几行代码,再次修改
def function():
time.sleep(1)
print('函数执行')
def timeer():
start_time = time.time()
function()
end_time = time.time()
print("函数的执行时间%s" % (end_time - start_time))
timeer()
# 我们要想也计算其他函数的时间怎么办?
def function1():
time.sleep(1)
print('函数执行')
def timeer(function):
start_time = time.time()
function()
end_time = time.time()
print("函数的执行时间%s" % (end_time - start_time))
timeer(function1)
# 又有了新的要求,我们想要在不改变原函数的调用方式来修改
# 可以用闭包来实现
def function2():
time.sleep(1)
print('函数执行')
def timeer(function):
def inner():
start_time = time.time()
function()
end_time = time.time()
print("函数的执行时间%s" % (end_time - start_time))
return inner
function2 = timeer(function2)
function2() #这样就可以在不修改函数调用方式的情况下增加功能
# python有一个语法糖的功能,例子如下
def timeer(function):
def inner():
start_time = time.time()
function()
end_time = time.time()
print("函数的执行时间%s" % (end_time - start_time))
return inner
@timeer
# 相当于:function2 = timeer(function2)
def function2():
time.sleep(1)
print('函数执行')
function2()
上述就是装饰器的基本方式
新的问题又来了,我们写的函数有参数怎么办呢?
我们直接给inner加上参数就好了啊
注意,此时参数应该怎么加,应该保证同时适用于有参数和无参数的函数
因为我们不知道函数有几个参数,所以应该用不定长参数
def timeer(function):
def inner(*args,**kwargs):
# 这样函数没有参数也可以用
start_time = time.time()
function(*args,**kwargs)
end_time = time.time()
print("函数的执行时间%s" % (end_time - start_time))
return inner
@timeer
def function2():
time.sleep(1)
print('函数执行')
@timeer
def add_num(num1,num2):
print(num1 + num2)
function2()
add_num(3,5)
不知道大家发现没有,我们还有一个问题没有解决,
对了,那就是函数的返回值的问题,我们怎么给有返回值的函数加装饰器呢?
我们从前面可以知道,我们加了装饰器,是会执行装饰器内部的inner函数
那么我们给inner函数加上返回值就好了啊,看代码:
def timeer(function):
def inner(*args,**kwargs):
# 这样函数没有参数也可以用
start_time = time.time()
res = function(*args,**kwargs)
# 此处用一个变量来接受函数的返回值。
end_time = time.time()
print("函数的执行时间%s" % (end_time - start_time))
# 函数的最后应该有返回值,而且这个返回值必须是function函数执行后的返回值,
# 那么我们就知道该怎么写代码了,我们用一个变量来接受函数function执行后的返回值就好了啊
return res
# 在此处返回
return inner
@timeer
def max_num(num1,num2):
if num1 > num2:
return num1
else:
return num2
print(max_num(3,5))
def outer(function):
def inner(*args,**kwargs):
# 函数执行前你想要做的
res = function()
# 函数执行后你想要做的
return res
return inner
那么到此处我们就已经掌握了装饰器的内容,上边是一个框架