Python不一致的UnboundLocalError行为.一个局部变量抛出错误,而另一个不抛出错误



我得到的是其中一个变量的UnboundLocalError,而不是另一个。

这是让我困惑的代码:

tokens=[]
token_count = 0
def extend():
for word in line.split():
tokens.append(word)
token_count += 1
lines = ['this is one line', 'this is another line']
for line in lines:
extend()
print(tokens)

运行这个你会得到错误:

UnboundLocalError: local variable 'token_count' referenced before assignment

但是删除token_count += 1行可以使代码运行良好。我知道这可以通过在函数定义后添加global token_count来解决。

我很难理解为什么Python不抱怨其他变量(例如,for word in line.split()tokens中的line(。这些变量都是在这个函数之外定义的,如果我为其中一个得到局部变量错误,我也应该为另一个得到它。

对这种行为有什么解释吗?

函数内的变量如果未在函数内赋值,则将从外部作用域继承。但是,如果您在函数内进行赋值,则该变量是局部变量(除非您根据情况使用nonlocalglobal语句(,并且在赋值之前无法使用其值。在执行token_count += 1时,您试图在函数内赋值之前查找现有值(以便向其加1(,但这将失败。

利用全局变量通常不是一种好的做法;更好的解决方法是返回一个值。例如:

def extend(tokens, line, token_count):
"extend tokens by the words in line; also return new token count"
for word in line.split():
tokens.append(word)
token_count += 1
return token_count
lines = ['this is one line', 'this is another line']
for line in lines:
token_count = extend(tokens, line, token_count)
print(tokens)

此函数不使用从外部范围继承的变量;所有内容都是函数或函数参数的局部内容。

token_count的情况下,它是一个参数,但您正在函数中重新分配它。这很好,但请注意,它不会更改主程序中token_count的值。稍后将其分配给主程序中的返回值(请参见token_count = extend(...)行(。

tokens的情况下,您通过调用现有可变对象(列表(的append方法而不是重新分配它(您不是在执行tokens = ...(来对其进行更改。更新后的值在主程序中也可见。

请注意,在这里,函数既修改可变参数(tokens(,又返回一个值。这有点不寻常,所以为了避免任何混淆,最好明确声明这就是它正在做的事情——因此在函数开始时使用docstring。

如果您需要以这种方式返回多个值,那么将它们打包到一个元组中,您可以在主程序中对其进行解压缩。


注意:在这种情况下,token_count的值可以简单地使用len(tokens)获得,而不是有一个单独的变量,但为了举例,代码没有利用这一事实

相关内容

最新更新