在尝试为类实例分配GUID的代码时,我写了类似于以下内容的内容:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
x_id = 0 # immutable
x_id_list = [0] # mutable
def fx(x):
global x_id # Disable to get "UnboundLocalError: local variable 'x_id' referenced before assignment"
if x is None:
x_id += 2
x_id_list[0] += 2
else:
x_id += 1
x_id_list[0] += 1
return (x_id - 1)
return x_id
expected = [x for x in xrange(10)]
actual = [fx(x) for x in expected]
assert(expected == actual), "expected = {}, actual = {}".format(expected, actual)
print x_id_list
print x_id
请注意,如果未定义全局作用域,则只有不可变x_id
会抛出UnboundLocalError
,但是可变x_id_list
继续正常工作,而不需要定义其全局作用域。 / p>
为什么?
答案 0 :(得分:0)
问题不在于x_id
是不可变的(它不是 - the integer value 0
is what's immutable),而是您无法通过{明确声明您的意图而无法分配给函数外部定义的变量{1}}。变更列表global
是指不会更改x_id_list
变量本身的值,因此是允许的。
如果您尝试x_id_list
,则会遇到同样的错误。它分配给变量,而不是改变值,这就是问题所在。
来自the docs:
在Python中,仅在函数内引用的变量是隐式全局变量。如果在函数体内的任何位置为变量赋值,则除非明确声明为全局,否则将其视为局部值。
虽然起初有点令人惊讶,但片刻的考虑解释了这一点。一方面,对指定的变量要求
x_id_list += [1]
可以防止意外的副作用。另一方面,如果所有全局引用都需要global
,那么您将一直使用global
。您必须将对内置函数或导入模块的组件的每个引用声明为全局。这种混乱会破坏global
声明用于识别副作用的有用性。
This answer也会详细介绍。
答案 1 :(得分:-1)
那是因为全局范围变量在函数中是只读的。
由于您正在修改变量x_id
,因此您需要在使用它之前引用它,否则Python将尝试创建一个本地函数的新变量。
在函数开头使用了global
表达式,您已告诉Python您需要在函数中引用和修改该变量。由于您正在修改变量x_id
,因此会发生这种情况。由于x_id_list
是可变的,因此您基本上不会明显地修改它(仅在内部,与x_id
不同,此类更改是外部的),因此,您不需要global
} keyword。