Skip to main content
 首页 » 编程设计

python之如何使子模块中的类在父模块的命名空间中可用

2025年05月04日17webabcd

这是一个 python 模块。 foo 位于 sys.path 中。

foo\ 
    __init__.py 
    bar\ 
        __init__.py 
        base.py 
            class Base(object) 
        derived.py 
            import foo.bar.base as base 
            class Derived(base.Base) 

我还没想好要做什么。如果我想从 derived 模块实例化 Derived 类,我可以很容易地做到这一点:

import foo.bar.derived as derived 
print(derived.Derived()) 

但是,我只想导入 bar 模块并调用 bar.Derived(),因为我计划在很多不同的模块中包含很多类,而且我不想处理所有这些触手可及的导入路径。我的理解是,我可以简单地将 Derived 导入 bar 模块的命名空间,方法是像这样修改我的项目:

foo\ 
    __init__.py 
    bar\ 
        __init__.py 
            from foo.bar.derived import Derived 
        base.py 
            class Base(object) 
        derived.py 
            import foo.bar.base as base 
            class Derived(base.Base) 

现在我应该能够执行以下操作:

import foo.bar as bar 
print(bar.Derived()) 

但是我得到一个 AttributeError 提示 foo 模块没有名为 bar 的子模块:

test.py             (1): import foo.bar 
foo\bar\__init__.py (1): from foo.bar.derived import Derived 
foo\bar\derived.py  (1): import foo.bar.base as base 
 
AttributeError: 'module' object has no attribute 'bar' 

事实上,我的原始测试代码(在顶部)也不起作用!当我尝试导入 foo.bar 时,出现错误。

我从这个错误中可以看出,__init__.py 中的 import 语句导致 derived.py 在 bar 之前执行已完全加载,因此它无法导入包含其自己的基类的模块(也来自 bar)。我来自 C++ 世界,超嵌套命名空间不是完整的,简单的前向声明可以解决这个问题,但我被引导相信我正在寻找的东西是可能的,至少是有点可以接受的 Pythonic 解决方案。我究竟做错了什么?使子模块中的类在父模块的命名空间中可用的正确方法是什么?

请您参考如下方法:

如果您使用的是 Python 2.5 或更高版本,请尝试使用显式相对导入 (http://www.python.org/dev/peps/pep-0328/#guido-s-decision):

test.py             (1): import foo.bar 
foo\bar\__init__.py (1): from .derived import Derived 
foo\bar\derived.py  (1): from . import base 

(请注意,如果您确实在使用 Python 2.5 或 2.6,则需要在模块中包含 from __future__ import absolute_import。)