【问题标题】:Simple cross import in pythonpython中的简单交叉导入
【发布时间】:2013-06-21 00:34:40
【问题描述】:

我想将不同类中的代码分开并将它们放到不同的文件中。但是这些类是相互依赖的。

ma​​in.py:

from lib import A, B

def main():
    a = A()
    b = B()
    a.hello()
    b.hello()

if __name__ == '__main__':
    main()

lib/_init_.py

from a import A
from b import B

lib/a.py:

import lib.B

class A():
    def __init__(self):
        print "A"

    def hello(self):
        print "hello A"
        b = B()

lib/b.py:

import lib.A

class B():
    def __init__(self):
        print "B"

    def hello(self):
        print "hello B"
        a = A()

是否可以在 Python 中做到这一点?

编辑:

我收到此错误消息:

pydev debugger: starting
Traceback (most recent call last):
  File "eclipse-python/plugins/org.python.pydev_2.7.1.2012100913/pysrc/pydevd.py", line 1397, in <module>
    debugger.run(setup['file'], None, None)
  File "eclipse-python/plugins/org.python.pydev_2.7.1.2012100913/pysrc/pydevd.py", line 1090, in run
    pydev_imports.execfile(file, globals, locals) #execute the script
  File "main.py", line 2, in <module>
    from lib import A, B
  File "lib/__init__.py", line 1, in <module>
    from a import A
  File "lib/a.py", line 1, in <module>
    import lib.B
ImportError: No module named B

【问题讨论】:

  • 你试过了吗?出了什么问题?

标签: python import cross-reference


【解决方案1】:

您可以在 hello 函数中导入另一个模块,而不是导入顶部的模块。

class B():
    def __init__(self):
        print "B"

    def hello(self):
        from lib import A
        print "hello B"
        a = A()

【讨论】:

  • 可以为整个班级进行这样的导入,还是在我需要 lib.A 的每个方法中都这样做?
  • 你可以在上面使用import lib,然后使用lib.A()
  • 如果输入太多,请尝试 import lib as x 并使用 x.A()
  • 更好地使用from lib import A...
【解决方案2】:

当你有两个类相互依赖时,通常意味着它们要么真的属于同一个模块,要么你的耦合太紧密,应该使用依赖注入来解决。

现在确实有几个极端情况,从函数内部导入是“最差”的解决方案,但这仍然是您应该尽可能避免的事情。

【讨论】:

    【解决方案3】:

    您的主要问题是您尝试导入一个类,但使用的语法仅适用于导入模块。具体来说,如果A 是在模块lib.a 中定义的类(并导入到lib 的顶级命名空间中),import lib.A 将永远无法工作。

    我建议你避免使用from _ import _ 语法,除非你真的需要它。这使得依赖关系更容易解决:

    lib/a.py:

    import lib.b # note, we're not importing the class B, just the module b!
    
    class A():
        def foo(self):
            return lib.b.B() # use the class later, with a qualified name
    

    lib/b.py:

    import lib.a # again, just import the module, not the class
    
    class B():
        def foo(self):
            return lib.a.A() # use another qualified name reference
    

    lib/__init__.py:

    from a import A # these imports are fine, since the sub-modules don't rely on them
    from b import B # they can be the public API for the A and B classes
    

    如果您不希望 ab 依赖于它们的包名称 lib,也可以使用相对模块导入。

    这肯定会起作用,因为 A 或 B 类实际上都不需要另一个存在才能被定义。只有在它们被导入之后,A 的实例才需要了解 B 类(反之亦然)。

    如果其中一个类继承自另一个类,或者以其他方式在顶层使用另一个类的实例,则您需要更加小心首先加载哪个模块,否则它可能仍会中断。

    【讨论】:

      【解决方案4】:

      如果只想导入一次,可以在类的构造函数中导入,并使变量全局化:

      class B():
          def __init__(self):
              global A
              from lib import A
              print "B"
      
          def hello(self):
              print "hello B"
              a = A()
      

      这会将 A 导入到全局变量中,并使其在模块中以可访问的形式出现。

      【讨论】:

        猜你喜欢
        • 2012-03-24
        • 2011-02-26
        • 1970-01-01
        • 1970-01-01
        • 2010-11-22
        • 2013-05-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多