【问题标题】:Declaring a class and subclass in two different files in python在python的两个不同文件中声明一个类和子类
【发布时间】:2017-03-21 17:59:07
【问题描述】:

我有两个文件,一个声明一个超类,其中涉及一个涉及子类的方法,另一个定义子类。

文件1:

from file2 import subclass

class superclass:
    def __init__(self):
        "Stuff"

    def method(self):
        temp = subclass()
        "Stuff"

文件2:

from file1 import superclass

class subclass(superclass):
    def __init__(self):
        "Stuff"

当我运行 file1 的代码时,我在 file2 中收到一个错误,即未定义超类。这是因为我在定义超类之前导入了 file2。

但是,如果我在定义超类之后导入 file2,我会在 file1 中收到一个错误,指出未定义子类。这是因为我在方法中使用了子类实例。

解决这个问题的一个方法是在一个文件中同时声明超类和子类,但我想知道是否有办法让它们在不同的文件中声明。

【问题讨论】:

  • 你不能有这样的循环导入。您不能将 file1 导入 file1,而 file2 导入 file1。为什么file2必须导入file1?
  • @Bryan Oakley 在声明子类之前子类不需要定义超类吗?
  • 是的,确实如此。定义子类之前必须先定义超类
  • 这就是为什么,据我所知,虽然也许还有另一种可能性,因此我问这个问题,file2 必须首先导入 file1。
  • 超类将子类的实例作为其数据的一部分是非常不寻常的。设计对象层次结构可能有更好的方法。这就像说狗是哺乳动物,哺乳动物定义的一部分是它有一只狗。也许如果你能解释为什么你需要这种不寻常的结构,我们就可以解决你面临的真正问题,而不是为你的解决方法找到解决方法。

标签: python class import subclass


【解决方案1】:

如果你看看 Python 是如何加载模块的,这个问题就很容易理解了:

  1. 你运行python file2.py
  2. Python 加载 file2.py 并开始执行它。
  3. Python 解析 from file1 import superclass
  4. Python 加载 file1.py 并开始执行它。
  5. Python 解析 from file2 import subclass
  6. 由于 file2 已加载,Python 尝试访问 file2.subclass
  7. Python 还没有解析类语句,所以subclass 还不存在。这会导致ImportError

只要在第二次导入发生时已经解析了类,Python 就可以处理循环依赖。有两种方法可以得到:

1) 在方法本身中导入file2

class superclass:
    def __init__(self):
        "Stuff"

    def method(self):
        from file2 import subclass
        temp = subclass()
        "Stuff"

这会导致在第一次调用 method 时发生导入,而不是在导入/加载 file1 时发生。 缺点是每次调用 method 时都会产生一些运行时开销,并且您必须确保仅在完成 ​​file1 的导入之后调用 method()

2) 在file1 的末尾导入file2,而不使用from import

class superclass:
    def __init__(self):
        "Stuff"

    def method(self):
        temp = file1.subclass()
        "Stuff"

import file2

这样file2 的循环导入发生在superclass 已经存在于file1 的命名空间中。当时file2 的命名空间是不完整的(file2.subclass 还不存在,所以from file2 import subclass 会失败)但只要在导入成功之前从未调用method,它就可以工作。缺点是您需要跟踪哪些导入语句需要位于文件底部,哪些需要位于顶部。任何错误都会导致ImportErrors,如果您的模块层次结构变得更加复杂,则可能难以跟踪。

也就是说,你真的应该重新设计你的类层次结构。循环导入(正如我上面解释的)非常脆弱,通常应该避免。

【讨论】:

    【解决方案2】:

    从方法中获取temp 并在子类中覆盖该方法。

    class superclass:
        def get_temp(self):
            return 'a superclass temp'
    
        def method(self):
            temp = self.get_temp()
            print(type(self).__name__, repr(temp))
    
    class subclass(superclass):
        def get_temp(self):
            return 'a subclass temp'
    
    
    superclass().method()
    subclass().method()
    

    输出:

    superclass 'a superclass temp'
    subclass 'a subclass temp'
    

    如果您需要method()subclass 不同,或者可能在superclass.method() 之前或之后做一些工作,请使用super 关键字。

    【讨论】:

    • 我需要在超类方法中的子类实例。这样做,如果我执行 superclass.method() 该方法将不会在内部使用子类实例。
    • self 是通过subclass().method() 调用时subclass 的一个实例
    • 或者如果你需要一个全新的subclass实例,你可以这样做:instance = type(self)()
    【解决方案3】:

    您可以在 file2 中包含以下行:

    if superclass in locals(): print pass
    else: 'Please define superclass'
    

    像这样:

    文件2:

    from file1 import superclass
    
    class subclass(superclass):
        if superclass in locals(): pass
        else: print 'Please define superclass'
        def __init__(self):
            "Stuff"
    

    现在尝试运行 file1 而不是 file2。它将提示“请定义超类”。但是子类已经注册了。一旦你运行类似的东西:

    x = superclass()
    

    子类变得可行。

    【讨论】:

    • 添加两行是否有效,或者您是否得到了不同的解决方案。如果您有不同的解决方案,请与我们分享。谢谢:)
    猜你喜欢
    • 2017-08-10
    • 2013-05-27
    • 2023-03-16
    • 2015-06-04
    • 2011-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多