python闭包与装饰器

python闭包

闭包并不只是一个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闭包概念

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

上一篇:Django admin 使用多个数据库


下一篇:python类杂项