我只是想知道,接下来的两个函数(Python 3.x)之间有什么区别
def first_example ():
counter = 0
def inc_counter ():
counter += 1
for i in range (10):
inc_counter ()
def second_example ():
counter = [0]
def inc_counter ():
counter[0] += 1
for i in range (10):
inc_counter ()
在赋值之前引用的第一个函数抛出异常,但第二个函数运行良好。有人可以解释一下,为什么python会记住数组,而不是整数?
答案 0 :(得分:5)
您将在第一个嵌套函数中分配counter
名称,使其成为局部变量。
在第二个示例中,您永远不会直接分配给counter
,使其成为自由变量,编译器正确连接到父函数中的counter
。你永远不会重新绑定名称,你只是改变了counter
所指的列表。
使用nonlocal
关键字将counter
标记为自由变量:
def first_example ():
counter = 0
def inc_counter ():
nonlocal counter
counter += 1
for i in range (10):
inc_counter()
答案 1 :(得分:3)
除非您明确标记global
或nonlocal
,否则无法将内部函数(也称为“闭包”)捕获的变量分配给它。
在第一个示例中,由于您尝试分配,因此counter
用于引用内部局部变量,而不是外部变量。在赋值之前引用此内部变量,这是一个错误。
在第二个示例中,您没有分配给变量,而是在其上调用__getitem__
来执行索引查找。所以没关系,counter
指的是外部变量。
答案 2 :(得分:1)
在第一个示例中,您的目的是将counter
更改为指向另一个对象(整数1,因为它从0开始)。
在第二个示例中,counter
仍然指向同一个对象:列表。列表的元素已更改。没有counter
的任务分配。
如果没有(在Python 3中)声明counter
非本地,则第一个是不允许的。在Python 2中,在任何情况下都不允许这样做。赋值+=
使counter
成为内部函数的局部变量。由于尚未在该范围内为其分配值,因此尝试使用它(如+=
也)会导致Python抱怨。
答案 3 :(得分:1)
在Python中,第一次在函数中分配变量时会创建变量。在您的第一个示例中,counter
在inc_counter
内分配,自编写
counter += 1
就像写作
counter = counter + 1
因此在该范围内创建了一个名为counter的新变量。
在第二个示例中,您只访问计数器变量,而不是分配它,因此不会创建新变量。