浅谈Python闭包和late binding机制

本文通过实例探讨Python中的闭包现象和late binding机制,揭示了在循环中定义函数为何会出现意外结果的原因,并提供了五种解决方案,包括函数工厂模式、函数默认参数、yield方法、functools.partial以及元组的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

从一个小问题开始

前几天在写代码的时候需要在循环中定义函数,却出现了预料之外的现象。先来看看下面这段简单的代码:

def generate_funcs():
	funcs = []
	for i in range(5):
		funcs.append(lambda: print(i))
	return funcs
	
for f in generate_funcs():
	f()

在循环过程中定义函数,我们希望5个函数分别输出0、1、2、3、4,即期望的输出是这样的:

0
1
2
3
4

然而运行结果是下面这样的:

4
4
4
4
4

大家不禁会纳闷儿了,我定义函数的时候明明白白写着 print(i)i 的值从 0 循环到 4,怎么执行出来就打印的都是 4 了呢?没错,这就是 Python 闭包中的 late binding 机制在“作祟"。这篇文章我们就好好讲讲 Python 闭包和 late binding 机制,避免大家再次踩坑。

从闭包 (closure) 谈起

我们要先介绍嵌套函数 (nested function) 和非局部变量 (non-local variable) 的概念。

定义在函数内部的函数叫做嵌套函数。我们都知道,函数有作用域,嵌套函数既可以访问自身作用域的变量,也可以访问外层函数作用域中的变量。看一个例子:

def print_function(msg):
	# printer is a nested function
    def printer():
        print(msg)
    printer()
    
print_function("Hello world!")

输出为

Hello world!

这里 printer 是一个嵌套函数,通过程序输出我们可以发现 printer 可以访问到外层函数 print_function 作用域中的 msg 变量。我们通常把函数参数或者定义在函数内部的变量叫做函数的局部变量 (local variable),而对于 printer 这个嵌套函数,msg 可以被访问到,但并不是 printer 的局部变量(而是外层函数的局部变量),我们把 msg 这样被嵌套函数访问的外层函数的局部变量称为嵌套函数的非局部变量 (non-local variable)。

我们把上面的程序稍作修改,得到下面的程序:

def print_function
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值