Python静态变量

2 投票
1 回答
1733 浏览
提问于 2025-04-17 06:58

我正在创建一个应用程序,使用一个基础类来存放所有的配置值、导入方法等等。

/
  - application.py
      + class foo
            + config = None
            + def loadconfig
  - otherfile.py
      + class bar
            + def getconfigvalue

所以,如果我启动 application.py 并运行 loadconfig,这个方法会把一个值加载到 foo.config 中,然后在这个方法里导入 otherfile.py(这样做是为了避免循环导入),接着创建一个新的 bar 对象,这个对象尝试从 foo.config 中获取一个配置值,但却显示 foo.config 是 None。你有什么建议吗?

简化的代码:
main.py

class Main:
    config = None
    @staticmethod
    def start():
        ## Load the configuration from a file, creating a dict in Main.config ##
        Main.other()

    @staticmethod
    def other():
        from otherfile import otherclass
        otherclass()

Main.start()

otherfile.py

from main import Main
class otherclass:
    def __init__(self):
        print(Main.config) ## Prints "None"

注意:这样安排是因为这在程序中确实是这样工作的;我觉得这可能和作用域有关

完整的源文件:
asgard.py: http://pastebin.com/jRkWzrPq
library/childcontainer.py: http://pastebin.com/6a561Nun

1 个回答

4

我来帮你分析一下你在使用 asgard 时遇到的问题,因为你给的简单例子有点问题:

  1. 你不能运行 main.py,这是因为有循环导入的问题。不过我觉得你是想运行 main.py(运行 otherfile.py 不会出现你遇到的问题)。
  2. 你其实从来没有给 Main.config 赋值。我不太清楚你打算在哪里给它赋值。

好了,接下来谈谈 asgard.py

在这里你会遇到一个关于模块 __main__ 的问题。当你运行 asgard.py 时,它的 __name____main__;你可能不知道的是,这实际上就是它在 sys.modules 中的模块名称——主模块是 sys.modules['__main__'],而不是 sys.modules['asgard']。然后,当你导入 library.childcontainer 时,它会尝试导入 asgard。这时它会查找 sys.modules['asgard'],但这个模块不存在,所以它会把 asgard.py 的内容导入到一个新的模块对象中。

如果你有另一个文件 main.py,里面写了 import asgard; asgard.Asgard.initialize()(暂时不考虑我下面提到的条件导入问题),你就不会遇到这个问题,因为 __main__ 模块会是那个 main.py,而 asgard.py 只会以 asgard 的名字被导入。另一个可行的解决方案是 if __name__ == '__main__': sys.modules['asgard'] = sys.modules['__main__']

还有,请你一定要记住,不要使用 if __name__ == '__main__': import ... 这种方式。这意味着如果你尝试 import asgard; asgard.Asgard.initialize(),比如说,它会失败并提示 'os' 未定义。请把这些导入放在文件的顶部,那里才是它们该在的位置。

撰写回答