跨模块和全局变量的 Python 导入

Posted

技术标签:

【中文标题】跨模块和全局变量的 Python 导入【英文标题】:Python imports across modules and global variables 【发布时间】:2011-12-31 05:31:33 【问题描述】:

我有一个似乎相当基本的问题,但我似乎无法在任何地方找到任何帮助。

file_a.py >>

from xyz import XYZ
class A:
    .
    .
    .

file_b.py >>

import file_a
from file_a import A
class B(A):
    def __init__(self):
        A.__init__(self)

    def someMethod(self):
        XYZ.doSomething()

XYZ.doSomething() 失败,提示 NameError: name 'XYZ' is not defined 即使从 file_a 完成的标准导入(如“import sys”)似乎也无法使其在 file_b 中可用。我认为应该可以。我的理解错了吗?如果是,那么有没有办法在文件之间有通用的导入和全局变量? (如果有帮助的话,我曾经是一名 C++ 和 java 程序员,现在开始使用 python。)

【问题讨论】:

【参考方案1】:

我的理解有误吗?

是的,因为from file_a import A 行仅将类A 导入file_b 的命名空间。 file_a 的命名空间保持不变。如果不是这样,那么同时使用这两种语法就没有什么意义了:

import modulename
from modulename import something

如果你的想法是对的,那么在第二种形式之后你总是可以使用modulename.someotherthing

如果是,那么有没有办法在文件中使用通用导入和全局变量?

是的,带有星号* 运算符:

from modulename import *

但这带来了命名空间污染的问题,例如from file_a import * 将导入file_b 以及所有在file_a 中完成的导入。你最终失去对你的进口的控制,这会在某个时候咬你...相信我!

当出于某种原因需要from module import * 时,命名空间污染的解决方法是在module 中定义variable __all__,它将应使用星号运算符导入的内容列入白名单。

HTH!

【讨论】:

【参考方案2】:

当您导入一个模块时,该模块中定义的所有变量都在其命名空间中可用。因此,如果XYZfile_a 模块中可用,则当您import file_a 时,您可以将XYZ 作为file_a.XYZ 访问。

这里的总体思路是,您的命名空间不应与其他命名空间的内容混杂在一起。

【讨论】:

【参考方案3】:

是的,你的理解是错误的。每个模块都有自己的命名空间,只有您在该文件中显式导入的内容才能在该命名空间中使用。

与其他答案相反,引用file_a.XYZ 并不是特别Pythonic,尽管这会起作用。相反,您应该在 file_b 的顶部导入 XYZ 和 sys。

【讨论】:

那是我的问题。我想避免在 file_b 等许多文件中重复一组导入。我知道将 XYZ 和 sys 导入 file_b 是可行的。 @ksrini 你不应该这样。显式导入模块使用的所有内容是很好的。它将所有依赖项整齐地列出在一个地方。请参阅 PEP20 - 显式优于隐式。 谢谢yak,这很有趣,很有见地!【参考方案4】:
import file_a
from file_a import A

我认为问题在于:你并没有真正导入 XYZ!

from fila_a import * 

可以解决你的问题,但不是好办法~~~

你可以在 file_b 中写这个:

from file_a import XYZ

完成了吗?

【讨论】:

以上是关于跨模块和全局变量的 Python 导入的主要内容,如果未能解决你的问题,请参考以下文章

Python 3:跨模块的全局变量的可见性

python 模块导入全局变量

Python实现跨文件全局变量的方法

Python实现跨文件全局变量的方法(摘抄版)

动态导入模块作为全局变量

python中各模块变量共享的问题。