我正在阅读Wes McKinney的 Python for Data Analysis 。我在这部分遇到了麻烦:
这是一个函数,它返回一个跟踪调用它的参数的函数:
def make_watcher():
have_seen = {}
def has_been_seen(x):
if x in have_seen:
return True
else:
have_seen[x] = True
return False
return has_been_seen
在一系列整数上使用它我得到:
In [496]: watcher = make_watcher()
In [497]: vals = [5, 6, 1, 5, 1, 6, 3, 5]
In [498]: [watcher(x) for x in vals]
Out[498]: [False, False, False, True, True, True, False, True]
然而,要记住的一个技术限制是,当你 可以改变任何内部状态对象(比如添加键值对) 一个字典),你不能在封闭的函数范围内绑定变量。 解决此问题的一种方法是修改字典或列表而不是 绑定变量:
def make_counter():
count = [0]
def counter():
# increment and return the current count
count[0] += 1
return count[0]
return counter
counter = make_counter()
在上面的文本中,作者的意思是“你不能在封闭的函数范围中绑定变量”?请详细说明这一说法。
答案 0 :(得分:2)
该示例旨在演示哪些方法有效,但未显示哪些方法无效。这是一个例子:
def make_counter():
count = 0
def counter():
# DOESN'T WORK
count += 1
return count
return counter
这不起作用,因为你试图将counter
重新绑定到一个新对象,整数1,你不能这样做。
答案 1 :(得分:1)
它不起作用,因为int
是Python中的不可变对象 - 一旦创建它们就无法更改 - 而list
是可变的。在Python中,最好将变量视为名称标签而不是容纳值的容器。该名称只是对实际存储值的物理内存块的一个很好的引用。因此,当您执行count += 1
时,您实际上是将名称标记count
移动到物理内存中的新地址,该地址的值比前一个值count
多一个。使用id()
可以看到这一点。
In [1]: a = 0
In [2]: id(a)
Out[2]: 140696027710384
In [3]: a += 1
In [4]: id(a)
Out[4]: 140696027710360
正如您所知,当我们增加a
时,其ID会发生变化。现在让我们对列表做同样的事情:
In [1]: a = [0]
In [2]: id(a)
Out[2]: 4389820176
In [3]: a[0] += 1
In [4]: id(a)
Out[4]: 4389820176
In [5]: a.append(1)
In [6]: id(a)
Out[6]: 4389820176
正如您所看到的,当我们在列表中增加一个值时,列表的id不会改变,当我们向列表中添加一个元素时,id也不会改变。