分配int vs数组之前引用的python变量

时间:2018-12-13 05:28:51

标签: python scope

当我使用func1编译此代码段时,在分配之前会出现有关引用输出的错误,这对我来说似乎很合理:

def func1():
    output += 1

output = 0
func1()
print(output)    

但是当我用func2编译此代码片段时,我没有收到错误,这对我来说似乎是不合理的。

def func2():
    output.append(1)

output = []
func2()
print(output)

有什么想法吗?预先感谢您,如果这是重复的,则对不起。在研究时,我没有看到类似标题的文章中提到这个特定问题。

2 个答案:

答案 0 :(得分:1)

这里的问题在于Python如何将名称绑定到变量

每次您在函数中编写赋值(诸如a = ba += 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 在本地绑定名称。可以使用globalnonlocal关键字来完成,例如:

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.
  • 但是,如果您有intstr这样的不可变类型,则可以但不能对其进行修改。

例如:

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"
  • 感谢Mark Tolonen的宝贵意见。最后,没有全局关键字,就不能重新分配全局变量,无论变量是可变的还是不可变的。

例如:

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关键字将它们包括在函数中,并根据需要使用它们。