python 中 闭包的理解

在python中,一个函数内部定义一个函数,并将内部函数返回,而一般内部函数会调用外部函数的参数和变量,并都将保存起来,即不会随着外部函数返回而释放,这就称为闭包。

我们来一步一步理解闭包
首先举个简单的例子

def createCounter(i):
    def counter():
        print(i)
    return counter

可以看到,外部createCounter函数中定义了内部counter函数,并将函数名return了回去

要理解闭包就必须理解对象,python中都是以对象的形式出现的,或者说是一个引用。执行函数的时候,return counter可以看成返回了内部函数一个引用。而python中在函数名后面加个()即表示调用该函数

上面这个函数,我们如果想打印i这个参数就要这么做

createCounter(123)()

大家可以自己动手试试,你可能会疑惑,有两个括号是什么情况。其实,第一个括号调用了外部函数,返回值为内部对象引用,再加一个括号调用该函数,于是就输出123了

s=createCounter(123)
s()

一般情况下大家可以这么调用,显得更加直观.。可以尝试打印s,即外部函数返回值,显示的是这个一个函数
<function main.createCounter..counter()>

在廖雪峰的python教程中有一个这样的题目
要求用闭包实现一个计数器函数。
由于内部函数不能更改外部函数参数与变量的值。我们有下面两种方法进行操作。

def createCounter():
    i=0
    def counter():
        nonlocal i
        i+=1
        return i
    return counter

counterA = createCounter()
print(counterA(), counterA(), counterA(), counterA(), counterA()) # 1 2 3 4 5
counterB = createCounter()
if [counterB(), counterB(), counterB(), counterB()] == [1, 2, 3, 4]:
    print('测试通过!')
else:
    print('测试失败!')

第一种我们可以使用nonlocal关键字,nonlocal专门用在函数或者其它作用域总使用外层变量但不是全局变量
第二种我们可以把要修改的数值放到可变的list中去,如下

def createCounter():
    i=0
    L=[i]
    def counter():
        L[0]+=1
        return L[0]
    return counter

最后说明一种容易出错的情况
请看下面的例子

def createCounter():
    i=0
    def counter():
        nonlocal i
        i+=1
        return i
    return counter
s=createCounter()
print(s(),s())   #1 2 

这个大家应该都知道输出应该是1,2
但是 如果换成了

def createCounter():
    i=0
    def counter():
        nonlocal i
        i+=1
        return i
    return counter
print(createCounter()(),createCounter()()) #1 1

结果就是1 1 了
为什么呢,前面说过,这个双括号的方式并没有问题,问题在于,两次引用的不是同一个对象,所以结果是独立的,所以最后输出的1 1 了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值