Python 绑定(关闭后期绑定)

Python Binding (Closure Late Binding)

我有一个关于 "python 绑定" 的问题(假设问题与此有关)。我在下面的问题上花了几个小时,并达到了 “closure late binding”“scope” 等主题。

据我所知,"closure" 被定义为一个包含自由变量的函数,并且它是后期绑定的。所以,我理解下面的代码输出 [[0, 1], [0, 1]] 而不是 [[0], [0, 1]].

# expected [[0], [0, 1]] but got [[0, 1], [0, 1]]
# this is because of "closure late binding"
def my_func():
    array.append(path)
    return

array, path = [], []
for value in range(2):
    path.append(value)
    my_func()

print(array)

所以,我尝试像下面这样设置参数以避免自由变量,进而关闭。我的预期输出是 [[0], [0, 1]] 但仍然是 [[0, 1], [0, 1]] 尽管该函数没有自由变量 in.

# expected [[0], [0, 1]] but got [[0, 1], [0, 1]]
# this function is not a closure as far as I know
def my_func(array, path):
    array.append(path)
    return

array, path = [], []
for value in range(2):
    path.append(value)
    my_func(array, path)

print(array)

我是否遗漏了一些基本的东西,比如后期绑定应用于任何功能?

这与其说是关于闭包,不如说是关于变量在 Python 中的工作方式(这与它们在许多其他语言中的工作方式没有什么不同,例如 Lisp 和 Java)。

变量不是一个可以放置值的框,它是一个保存对象引用的框。同样,列表中的每个项目都是对值的引用。

让我们看看你的第二个程序。因为 my_func 并没有真正做任何事情,我们可以通过内联它来简化一点,像这样:

array, path = [], []
for value in range(2):
    path.append(value)
    array.append(path)

print(array)

当我们运行这个时会发生什么?首先,我们初始化 arraypath 以保存对空列表的引用:

array --> []
path  --> []

然后我们开始 运行 循环,然后执行 path.append(0)。现在看起来像这样:

array --> []

path  --> [*]
           |
           v
           0

然后我们将 path 引用的任何内容附加到 array:

中,即包含对“零”对象的引用的列表对象
array --> [*]
           |
           v
path  --> [*]
           |
           v
           0

然后我们 运行 循环的下一次迭代,将 1 添加到 path 引用的列表中:

array --> [*]
           |
           v
path  --> [*, *]
           |  |
           v  v
           0  1

最后,我们再次将 相同的列表 附加到 array:

array --> [*, *]
           | /
           |
           v
path  --> [*, *]
           |  |
           v  v
           0  1

所以当我们完成后,array 持有对一个列表的引用,该列表又持有对一个列表的两个引用,该列表持有对整数 0 和 1 的引用。