闭包并不只是一个python中的概念,它在函数式编程语言中应用较为广泛。
在这里,我们只浅谈python闭包。
闭包,又称闭包函数或者闭合函数,闭包中外部函数返回的不是一个具体的值,而是一个函数。一般情况下,返回的函数会赋值给一个变量,这个变量可以在后面被继续执行调用。
我们来看一个例子
def a(param1): def b(param2): return param1 + param2 return b fun1 = a(1)#基数1 fun2 = a(2)#基数2 fun3 = a(3)#基数3 print(fun1(1)) #1+1 print(fun2(1)) #2+1 print(fun3(1)) #3+1
函数a的返回是函数b,而函数b的返回是a之前的param1加上b里再给的参数param2。
我们可以这样形象地认为,fun1是相加的函数,而第一个加数已经在定义fun1的时候锁死了,我们传给它的参数只能是第二个加数。
接下来,我们定义a(param1)是外函数,b(param2)是内函数,这样来解释闭包:
在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。
我们在例子中加入一些print
def a(param1): print(a) def b(param2): print(b) return param1 + param2 return b fun1 = a(1) fun2 = a(2) fun3 = a(3) print(fun1(1),fun1(1),fun2(2),fun3(3))
运行,得到
<function a at 0x000001AC399668B0> <function a at 0x000001AC399668B0> <function a at 0x000001AC399668B0> <function a.<locals>.b at 0x000001AC39966940> <function a.<locals>.b at 0x000001AC39966940> <function a.<locals>.b at 0x000001AC399669D0> <function a.<locals>.b at 0x000001AC39966A60> 2 2 4 6
这可以看出,在内存中,外部函数a是只存在唯一一个的,而它的内部函数b是一样的代码,不一样的对象。
浅显地说到这里,深入的话我推荐一篇博客
理解Python闭包概念
在了解了闭包这个概念之后,我相信装饰器就可以很好理解了。
这里,也从一个简单的例子说起。
def makebold(fn): def wrapped(): return "<b>" + fn() + "</b>" return wrapped def makeitalic(fn): def wrapped(): return "<i>" + fn() + "</i>" return wrapped def welcome(): return "hello world" a=makeitalic(welcome) b=makebold(a) print(a()) print(b()) #结果 #<i>hello world</i> #<b><i>hello world</i></b>
我们在两个函数里内嵌的不同的wrapped函数,负责给我们的"hello world" 左右添加起始闭合标签。这就是python 中装饰器做的事情,封装一个函数,并用自己的方法来修改它的行为。
当然,这里没有出现@符号,这是一种语法糖,我们给它加上。
什么是语法糖?
在不改变其所在位置的语法结构的前提下,实现了运行时等价。
eg:在 C 语言里用 a[i] 表示 *(a+i),用 a[i][j] 表示 *(*(a+i)+j)
def makebold(fn): def wrapped(): return "<b>" + fn() + "</b>" return wrapped def makeitalic(fn): def wrapped(): return "<i>" + fn() + "</i>" return wrapped @makebold @makeitalic def welcome(): return "hello world" print(welcome()) #输出<b><i>hello world</i></b>
理解Python闭包概念
flask之路由route