【问题标题】:What's the logic behind this python global scoping magic?这个 python 全局作用域魔法背后的逻辑是什么?
【发布时间】:2013-05-12 13:37:23
【问题描述】:

我在 python 中搞乱了范围,发现了一些我认为很奇怪的东西:

g = 5

def foo(a):
    if a:
        global g
        g = 10
    else:
        g = 20


print("global g: ",g)

foo(False)
print("global g: ",g) # 20?! What?

foo(True)
print("global g: ",g)

我认为第二次打印应该是“5”,因为全局语句从未执行过,但很明显,输出是 20(!)。

这背后的逻辑是什么?

【问题讨论】:

  • 如果您有兴趣玩转这些东西,您应该学习字节码的基础知识并玩转dis 模块。 (在顶层使用global 定义foo 后尝试dis.dis(foo),在if 内部,根本不存在。)
  • 我实际上确实使用了 dis 模块,所以我看到 g = 20 被放入了全局范围。因此,我怀疑给定的答案,但想确定:)

标签: python programming-languages scope lexical-scope


【解决方案1】:

python编译器使用global关键字将函数范围内的名称标记为全局。

只要您在函数中的任何位置使用它,该名称就不再是本地名称。

请注意,if 不会引入新的作用域,只有函数和模块会(类、列表、字典和集合理解是函数作用域的特例)。

一种(难以阅读且非 Pythonic)的解决方法是使用 globals() 函数:

def foo(a):
    if a:
        globals()['g'] = 10
    else:
        g = 20

【讨论】:

  • 还值得指出的是,在 Python 中(与 C 和朋友不同),if 块不是新范围; global 语句的作用域就是函数。
  • 有趣。我不会期望像 python 这样的动态语言会出现这种情况。是否就做出此决定的原因进行了讨论?
  • @abarnert:确实;扩展了做什么创建一个新的范围。
  • @monoceres:必须在函数定义时决定每个名称的名称,否则闭包会更复杂。 (看看 foo.func_code.co_namesco_varnames 等的内容)
  • @monoceres:至于讨论......真的,对于自 Python 1.0 以来的所有内容,每年都不会在 python-ideas 或 -dev 上争论,也没有在Design FAQ,“为什么”有时很难找到……但这带来了一个想法:建议在 python-ideas 上更改它,你会得到 Guido 和其他人告诉你为什么这是一个愚蠢的想法。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-17
  • 1970-01-01
相关资源
最近更新 更多