为何持有adder函数的变量b未每次调用都输出4?请求解惑
为什么闭包调用多次输出不是始终为4?
嘿,这个问题问到点子上了!很多刚接触闭包的开发者都会掉进这个误区,我来给你讲明白~
首先咱们先还原一下你大概率遇到的代码场景(毕竟没贴代码,但这个坑太常见了):
def create_adder(): x = 3 def adder(y): nonlocal x # 要是在JS里就是直接修改x,不用写这个声明 x += y return x return adder b = create_adder() print(b(1)) # 第一次输出4 print(b(1)) # 第二次居然输出5,不是4?!
核心原因:闭包抓的是「作用域引用」,不是「变量固定值」
你以为b(也就是adder函数)记住的是x=3这个固定值?错啦!它记住的是整个包含x的作用域的引用。也就是说,adder里用的x,和create_adder函数里的x是同一个变量,只是通过闭包“拎”出来用了。
- 第一次调用
b(1)时,x += 1把原作用域里的x从3改成了4,然后返回4; - 第二次调用时,这个x已经是4了,再加1自然就变成5了——因为作用域里的x已经被修改过,闭包会一直用这个更新后的变量。
那怎么让每次调用都输出4?
如果想让每次调用都得到4,你得让闭包只读取x的值,而不修改它。比如把代码改成这样:
def create_adder(): x = 3 def adder(y): return x + y # 只读取x的值,不修改它 return adder b = create_adder() print(b(1)) # 4 print(b(1)) # 还是4!
这时候x在作用域里从来没被修改过,始终是3,所以每次加1都是4。
说白了,关键就看你在闭包里有没有修改捕获的变量——如果只是读,那值就一直是最初的;如果改了,那修改会存在作用域里,后续调用就用新值啦。
内容的提问来源于stack exchange,提问作者pragun
相关产品推荐
相关产品推荐

