武夷山------深入理解Python中的闭包函数

python学习网 2017-11-27 06:00:04

在学习装饰器的过程中,我们必须先越过一个坎,那就是闭包函数。

关于闭包函数,有三个可以参考的定义:

闭包函数的定义:

第一:定义在内部的函数包含对外部作用域(而非全局作用域)变量的引用,该内部函数就称为闭包函数。

第二:简单的说,闭包就是根据不同的配置信息得到不同的结果。

第三:简单的说,内部函数可以使用外部函数变量的行为,叫做闭包。


闭包函数的两个特点:

第一:闭包函数一定是在一个函数的内部进行定义的;

第二:定义在内部的函数必须包含对外部作用域变量的引用。

只要满足上面两个条件,就称为闭包函数。


下面我们进行闭包函数的判断:

示例1:

def f1():
    def f2():
        x = 1
        print(x)

在上面的例子中,f2这个函数虽然是在一个函数内部进行定义的,但是并没有包含对外部作用域变量的引入,所以f2这个函数并不是闭包函数。

示例2:

x = 1
def f1():
    def f2():
        print(x)

在上面的例子中,f2这个函数虽然是在一个函数内部进行定义的,但是并没有包含对外部作用域变量的引入,因为x=1是一个全局作用域变量,所以2这个函数并不是闭包函数。

 闭包函数实例场景:惰性计算(延迟计算)将某种状态先保存起来,什么时候用就用。

示例1:

#!/usr/bin/python
# -*- coding:utf-8 -*-

def make_adder(m):
    def adder(n):
        return m + n
    return adder

p = make_adder(30)
q = make_adder(40)

#本是相同的函数adder,但是由于配置信息的不同,导致运行结果并不相同
print(p.__name__,q.__name__)
print(p(20))
print(q(20))


#查看相应的配置信息:即闭包函数引用外部作用域的变量
print(p.__closure__[0].cell_contents)
print(q.__closure__[0].cell_contents)

 在上面的例子中,我们不难发现,无论是make_adder(30)还是make_adder(40)返回的都是adder这个函数对象,但是由于配置信息的不同,导致运行结果并不相同。

还是那句话:在python中,函数是第一类对象,函数的名字相当于指针变量,里面存放的是对应函数体的地址。

示例2:

#!/usr/bin/python
# -*- coding:utf-8 -*-

def foo(m,n):
    def bar(a):
        return m + n + a
    return bar

fun = foo(10,50)
print('指针变量fun的数值是:%s'%fun)
print(fun.__name__,fun.__closure__)
for item in fun.__closure__:
    print(item.cell_contents)
print(fun(20))

相应debug视图:

OK,闭包函数就讲到这里。

 

阅读(852) 评论(0)