python基础--闭包函数和装饰器
程序员文章站
2022-03-20 16:52:51
首先我们应该知道一件事:函数的定义域跟定义位置有关系,而跟调用位置没有关系。闭包函数:定义:内层函数对外层函数而非全局变量的引用,就叫做闭包函数 闭包会一直存在在内存中,不会因为函数执行结束而被释放先看个例子: def outer(): num = 1 def inner(): nonlocal n ......
首先我们应该知道一件事:函数的定义域跟定义位置有关系,而跟调用位置没有关系。
闭包函数:
定义:内层函数对外层函数而非全局变量的引用,就叫做闭包函数
闭包会一直存在在内存中,不会因为函数执行结束而被释放
先看个例子:
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
那么到此处我们就已经掌握了装饰器的内容,上边是一个框架