2

我有一个父类和一个子类,每个类都在自己的单独文件中。如果这两个类在一个文件中,我的 MWE 可以工作。如果我将它们分别拆分为单独的文件,我不知道如何相互导入。这是MWE:

cat test.py
#!/usr/bin/env python3

from main_win import MainWin

test = MainWin()
test.click()

cat main_win.py
#!/usr/bin/env python3

from sub_win import SubWin

class MainWin:
    def __init__(self):
        print('Created main window')
    def click(self):
        options = SubWin()

cat sub_win.py
#!/usr/bin/env python3

from main_win import MainWin

class SubWin(MainWin):
    def __init__(self):
        print('Created sub window')

如果我执行test.py并使用上面定义的循环导入,我会收到以下错误:

ImportError:无法从“main_win”(/home/basil/scratch/trash/pythonInheritance/p03/main_win.py)导入名称“MainWin”

编辑:有有效的评论质疑我的类结构:我需要继承吗?我可以添加一个超类,上面的两个类都可以继承吗?这些都是非常好的评论,我会仔细考虑。当然,在回答这些问题时,MWE 对您没有用处。现在,让我们假设类结构不会改变。那么如何解决这个问题呢?通过将两个模块合并为一个,还是有其他方法?

4

2 回答 2

1

您有一个循环导入。main_win.py进口... sub_win.py_main_win.py

要解决此问题并使代码保持原样,您可以从技术上from sub_win import SubWin移至MainWin.click(). 不过,这绝对不是我的建议,您可能应该重新设计并重新考虑这种方法来实现您想要实现的任何目标。

于 2018-10-18T02:15:27.213 回答
0

您的问题是您有循环导入情况。main_win模块导入,sub_winsub_win尝试导入main_win回来,但它不能正常工作,因为当模块尝试导入它MainWin时该类还不存在。sub_win

有几种可能的解决方案。

通常最好的解决方案是摆脱两个类之间的循环依赖。循环进口并不被禁止,但对它们的需求通常表明设计草率。也有很多方法可以修复依赖关系。在示例代码中,您根本不需要SubWin继承MainWin,因此您可以删除继承。如果他们确实需要共享一些公共代码或信息,也许他们都应该从一个共同的祖先(例如Window)继承它,共享的东西可以去哪里。另一种选择将使这两个类不相关,但MainWin将信息SubWin需要传递给其构造函数(例如options = SubWin(some_data))。

另一种选择可能是将导入推迟sub_win到命名空间MainWin中存在之后main_win。您可以通过将from sub_win import SubWin语句移动到代码中更下方的位置来做到这一点。它可以保留在模块的顶层,低于 的定义MainWin,也可以放在click使用它的方法内部(因此它将是函数中的局部变量,而不是全局变量)。

最后一个想法是将您的类放在同一个模块中,这样您就根本不需要导入语句。如果您的两个类像您当前的设计所暗示的那样紧密耦合,那么绝对没有理由将它们分成单独的模块。Python 与其他一些编程语言(如 Java)非常不同,Java 的默认设置是每个类都有自己的源文件。Python 项目通常具有包含许多类和全局函数的大型模块。只有当模块变得如此之大以至于您经常发现自己使用它们的一部分代码而不需要其他部分时,您才需要将它们拆分。

于 2018-10-18T02:58:42.510 回答