【问题标题】:Why am I able to global a non-existing variable in python为什么我能够在 python 中全局化一个不存在的变量
【发布时间】:2018-07-11 14:45:00
【问题描述】:

首先,我完全理解global语句的含义和使用方法。

现在,让我们看看这个:

x = 100
def f():
    global x
    global xxx
    x = 99
    return x

print(f())
# >>> 99
print(x)
# >>> 99

可以看到,通过使用global x,我成功的改变了全局环境中x的值。

但是xxx根本不存在,为什么我允许全局它,即使函数执行也不会带来任何错误?

【问题讨论】:

  • 我认为global xxx 只是一个多余的语句,但由于它是有效的python 代码,python 解释器只会忽略它,就像母亲忽略你幼稚的错误一样。不过我可能是错的。
  • 但是我以为python在运行之前会检查所有编译中的变量边界情况,如果有边界错误,就不会执行?
  • 您可以使用global 初始化变量,只需给它们一个名称,尽管我不确定这些变量的默认行为是什么。奇怪的是,我在 Python 3 文档中找不到关于 global 关键字及其使用的任何内容。
  • 我修改了我之前的声明:您可以使用裸global x 声明全局变量,但如果您没有为它们分配任何内容,则无法访问它们。我认为解释器只是把它扔掉并忽略它。

标签: python global


【解决方案1】:

global x 不定义、声明或以其他方式创建x。它只是说明在当前函数范围内是否以及何时分配x(无论该分配是在global 语句之前还是之后,这就是为什么强烈建议在开头使用global 语句的原因函数),分配给该名称的全局变量,而不是局部变量。实际的创造仍然是实际分配的工作。

换句话说,global 本身不会生成任何字节码;它只是修改其他赋值语句可能生成的字节码。考虑这两个函数:

def f():
    global x
    x = 99

def g():
    x = 99

这两个函数的字节码的唯一区别是f 使用STORE_GOBAL 作为global 语句的结果,而g 使用STORE_FAST

>>> dis.dis(f)
  5           0 LOAD_CONST               1 (99)
              3 STORE_GLOBAL             0 (x)
              6 LOAD_CONST               0 (None)
              9 RETURN_VALUE
>>> dis.dis(g)
  8           0 LOAD_CONST               1 (99)
              3 STORE_FAST               0 (x)
              6 LOAD_CONST               0 (None)
              9 RETURN_VALUE

如果您要添加“未使用”global 语句,例如在

def h():
    global xxx
    x = 99

生成的字节码与g 无法区分:

>>> dis.dis(h)
  3           0 LOAD_CONST               1 (99)
              2 STORE_FAST               0 (x)
              4 LOAD_CONST               0 (None)
              6 RETURN_VALUE

【讨论】:

  • 你能看看这个,也许能解释一下为什么 nonlocal 的行为不同?stackoverflow.com/questions/51287522/…
  • nonlocal 不会回退到全局范围;它只在当前作用域和全局作用域之间 的其他作用域中查找。因为x 不存在于f 的范围内(g 的本地范围和全局范围之间的唯一范围),所以在x = x * 99 的右侧查找x 失败。请注意,使用nonlocal 还允许解析器将其作为SyntaxError 捕获,而不是查找错误。
  • g被定义时,f的范围已经建立,允许解析器识别x是否在范围内,即使f本身实际上并不提供分配直到 之后 def g 被解析。 (我假设这不是严格意义上的代码不可解析的语法错误,而是在 f 的源代码实际上完全解析之后采取的静态分析步骤。)
猜你喜欢
  • 1970-01-01
  • 2016-10-07
  • 1970-01-01
  • 1970-01-01
  • 2015-06-25
  • 1970-01-01
  • 2021-01-14
  • 1970-01-01
  • 2021-01-22
相关资源
最近更新 更多