【问题标题】:Confusing python variable scope令人困惑的python变量范围
【发布时间】:2021-05-15 11:35:36
【问题描述】:

我通常不会对 python 中的变量范围考虑太多,但我想看看是否有一个明确的解释。给定两个名为 main.pyutils.py 的文件:

utils.py

def run():
    print(L)

ma​​in.py

import utils

def run():
    print(L)

if __name__ == '__main__':
    L = [1,2]
    run() 
    utils.run() 

main.py 中的第一个 run() 调用运行良好,尽管 L 没有被输入到 run(),并且 utils.run() 调用引发了 NameErrorL 是一个全局变量,可用于main.py 中定义的所有函数吗?

如果我用from utils import * 而不是import utils 导入utils,那会改变什么吗?

【问题讨论】:

    标签: python scope global-variables


    【解决方案1】:

    它是模块级范围。模块中定义的全局变量可用于同一模块中定义的所有函数(如果它没有被覆盖)。另一个模块中的函数无法访问另一个模块的变量,除非它们导入它们。

    关于“如果我使用 from utils import * 而不是 import utils 导入 utils,那会改变什么吗?”: 不,范围是在解析时确定的。

    检查 this 了解更多信息。

    值得注意的是:

    重要的是要认识到范围是由文本确定的:全局 模块中定义的函数的范围是该模块的命名空间,无论 从哪里或通过什么别名调用该函数。另一方面, 名称的实际搜索是在运行时动态完成的 [...]

    因此,在一个模块中定义的变量的两个函数的全局范围是它们被定义的模块。首先,它的模块后来也有一个它使用的全局变量的定义,但没有另一个模块,当是时候在函数运行时检查变量了,每个人都会检查自己模块的变量定义,一个找到,另一个没有。

    【讨论】:

      【解决方案2】:

      Python's FAQ。它们的作用域实现是便利性和全局危险性之间的折衷。

      如果变量仅被函数引用,则变量被视为全局变量,如果要编辑它们,则需要在函数体内显式声明为全局变量(例如 global foo )。如果您编辑run() 以尝试更改 L 的值,则会收到错误消息。

      这里发生的情况是您的 Python 代码导入了 utils,然后运行 ​​run()。该函数发现您正在寻找一个名为“L”的变量,并检查您的全局命名空间。

      【讨论】:

      • 您应该澄清if __name__ == '__main__': 块不在函数内。通常人们定义一个像def main() 这样的函数,然后在他们的__main__ 块中调用main()。因此,您在其中声明的任何内容显然都是全球性的。如果你在定义L之前调用utils.run(),那么你会得到一个错误,但如果你在之后调用L,那么将不会有错误。
      • 这两个答案都很好。我没有意识到将变量放在__name__ == '__main__' 块中会将它们定义为模块的全局变量。我现在清楚地理解了将main() 函数调用放在__main__ 块内的必要性。谢谢!
      猜你喜欢
      • 2019-05-23
      • 1970-01-01
      • 1970-01-01
      • 2016-02-19
      • 1970-01-01
      • 1970-01-01
      • 2012-04-09
      • 1970-01-01
      • 2017-07-13
      相关资源
      最近更新 更多