闭包和装饰器:(人生苦短,我用python)
一、闭包:
-
函数只是一段可执行代码,编译后就“固化”了,每个函数在内存中只有一份实例,得到函数的入口点便可以执行函数了。函数还可以嵌套定义,即在一个函数内部可以定义另一个函数,有了嵌套函数这种结构,便会产生闭包问题。
-
闭包实际上就是函数嵌套,就和循环嵌套和if条件嵌套的思想一样,只不过函数嵌套更复杂一点。
-
闭包是由函数及相关环境的引用环境组合而成的实体(即:闭包 = 函数块 + 引用环境
-
闭包案例:
案列01:
# 外层函数 outer def outer(n): num = n # 内嵌函数 inner def inner(): return num+1 return inner # 注意:return是 outer返回的结果,inner为outer函数的内嵌函数的名字,并没有执行inner (判断依据;看返回的函数是否加小括号) print(outer(3)()) # 4 print(outer(3)) # <function outer.<locals>.inner at 0x0000026610D58400> print(outer(5)()) # 5 # 我们执行outer函数返回的结果为:inner 而inner()则执行函数 # 注意:print(inner()) 这种写法是错误的 必须要先调用外层函数outer
案例02:
def outer(n): num = n def inner(): num = num + 1 return num return inner print(outer(1)()) # UnboundLocalError: local variable 'num' referenced before assignment
仔细观察案例01和案例02,我们可以发现区别就在于内嵌函数的使用。在案例01中,内嵌函数直接返回num+1,而在案例02中,内嵌函数内先执行num=num+1的操作,然后才返回的。根据运行结果的提示,显示错误就在num,原因是因为:在python里,只要看到了赋值语句,就会认为赋值语句的左边是一个局部变量。
num = num + 1
这段代码里,num
在=
的左边,python解析器会认为我们要修改inner
函数里num
这个局部变量,而这个变量使用之前是未声明的,所以会报错。**解决方案:**使用nonlocal 关键字
def outer(n): num = n def inner(): # 在内部函数里边,我们修改外部函数的局部函数, # 需要加nonlocal nonlocal num # 修改前使用nonlocal关键字对 num 变量进行说明 num = num + 1 return num return inner print(outer(2)())
二、装饰器:
先认识装饰器:
-
def