当我使用func1编译此代码段时,在分配之前会出现有关引用输出的错误,这对我来说似乎很合理:
def func1():
output += 1
output = 0
func1()
print(output)
但是当我用func2编译此代码片段时,我没有收到错误,这对我来说似乎是不合理的。
def func2():
output.append(1)
output = []
func2()
print(output)
有什么想法吗?预先感谢您,如果这是重复的,则对不起。在研究时,我没有看到类似标题的文章中提到这个特定问题。
答案 0 :(得分:1)
这里的问题在于Python如何将名称绑定到变量。
每次您在函数中编写赋值(诸如a = b
或a += b
之类的内容时,Python都会将该名称本地绑定到整个 >功能范围。这意味着任何在函数外部声明的具有该名称的变量都将被忽略。
例如:
a = 1 # This variable is ignored.
def foo():
print(a) # "a" hasn't been defined yet!
a = 2 # This causes "a" to bind to a local variable.
这将在print语句中产生一个UnboundLocalError
,因为Python看到a
被分配给函数的后面,并在本地绑定它,而忽略了您在函数外部定义的变量。由于a
仅在打印语句之后 定义,因此会出现错误。
这可能非常令人困惑,因为删除a += 2
行将导致print语句按预期工作!
解决方案是明确告诉Python 不在本地绑定名称。可以使用global
和nonlocal
关键字来完成,例如:
a = 1
def foo():
nonlocal a # or: global a
print(a)
a += 2
global
告诉Python在模块的全局范围内绑定名称,而nonlocal
(在Python 3中引入)告诉Python绑定到封闭范围(例如,如果您在函数内部定义了函数)。
documentation中有一个很好的解释(带有示例):-)
一旦我们理解了这些规则,我们可以看到您的第一个示例失败,因为您正在尝试递增尚不存在的变量。 output += 1
等效于output = output + 1
,它将触发本地名称绑定。
另一方面,您的第二个示例不会触发错误,因为您没有分配给output
(而是对其进行变异),因此它将绑定到您定义的全局变量。
答案 1 :(得分:0)
在Python中,在函数中调用时,全局变量不能完全相同。
Python中的数据类型(高级)可以分为“可变”和“不可变”。
list
之类的可变数据类型,则可以在函数中对其进行访问和修改,而无需使用global
关键字对其进行引用。例如:
l = []
def foo():
l.append(1) #works
foo()
print(l) # prints [1], so foo() changed the global list l.
int
或str
这样的不可变类型,则可以但不能对其进行修改。例如:
someString = "abcdef"
def foo():
print(someString[2]) # prints "c"
someString += "l" # error as someString cannot be modified unless you include it in the function foo() with the global keyword as shown below.
str
之类的不可变类型的全局变量,您必须先将其包含在global
关键字中,然后才能像任何局部变量一样自由使用它。 例如:
someString = "abcdef"
def foo():
global someString # This now includes someString in foo() scope and is allowed to be modified.
print(someString[2]) # prints "c"
someString += "l" # works as expected
print(someString) # prints "abcdefl"
例如:
someInt = 1
someStr = "abc"
someList = [1,2,3]
def foo():
someInt += 3 # error, local variable referenced before assignment.
someStr += "def" # error, local variable referenced before assignment.
someList += [4] # error, local variable referenced before assignment. Note that this is **not** the same as doing someList.append(4).
要完成上述工作,请通过global
关键字将它们包括在函数中,并根据需要使用它们。