【问题标题】:Why does the scope work like this?为什么作用域会这样工作?
【发布时间】:2016-10-04 06:10:24
【问题描述】:

这个问题是我的一个学生提出的关于以下代码的问题的结果,老实说,我完全被难住了。任何帮助将不胜感激。

当我运行这段代码时:

#test 2

a = 1

def func2(x):
    x = x + a
    return(x)

print(func2(3))

它工作得很好。它能够获取全局范围的变量 a 并使用它的值来执行计算并返回值 4。

但是,如果我将其更改为:

# test 3

a = 1

def func3(x):
    a = x + a
    return(x)

print(func3(3))

然后我得到一个错误:

赋值前引用的局部变量'a'

为什么只有当我想将函数内的 a 的值更新为基于其原始值的新值时才会出现此错误?我不明白什么?我觉得第二段代码应该可以正常工作。

提前感谢您提供的任何帮助和见解。

【问题讨论】:

  • 就我个人而言,我总是在函数顶部的全局变量上声明global,即使我只是在阅读它们(这绝对是不必要的)。它是纪录片,在某种程度上是防御性的。一种看待它的方式是在 Python 中不鼓励使用全局变量,因为它们破坏了封装。所以,是的,他们有点尴尬。尽量避免它们。

标签: python python-3.x variables scope global-variables


【解决方案1】:
a = 1

def func3(x):
    global a
    a = x + a
    return(x)

print(func3(3))

现在应该可以了。

当您将语句a=x+a 放入函数中时,它会创建一个新的局部变量a 并尝试引用它的值(显然之前没有定义过)。因此,您必须在更改全局变量的值之前使用global a,以便它知道要引用哪个值。

编辑:

函数的执行引入了一个新的符号表,用于 函数的局部变量。更准确地说,所有变量 函数中的赋值将值存储在本地符号表中; 而变量引用首先查看本地符号表,然后 在封闭函数的局部符号表中,然后在全局 符号表,最后是内置名称表。因此,全球 变量不能在函数内直接赋值 (除非在全局语句中命名),尽管它们可能会被引用。

【讨论】:

  • 啊!非常有趣。非常感谢您的解释。现在完全有道理,但我必须承认这是一个非常奇怪的小警告!
  • 如果这为您解决了问题,您是否可以接受答案,以便发帖人获得信任并且 SO 认为问题已结束?是的,这种行为是 Python 的“陷阱”之一。
  • 是的。我打算这样做,但它不会让我这么快就选择它作为答案。
【解决方案2】:
def func3(x):
    a = x + a
    return(x)

在 a = x + a (So, x + a) 的右侧,'x' 作为变量传递,其中 'a' 没有作为变量传递,因此是错误的。 不使用全局变量:

    a = 1

    def func3(x, a=2):
        a = x + a
        return(x)

    func3(3)

返回:5

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-27
    • 1970-01-01
    • 2015-02-10
    相关资源
    最近更新 更多