【问题标题】:Python factory class inheritancePython工厂类继承
【发布时间】:2023-04-08 09:16:01
【问题描述】:

如何检查一个类是否是由工厂类创建的父类的子类?

考虑以下简单的例子:

from itertools import count
def basefactory():
    class Base:
        _idc = count(0)
        def __init__(self):
            self._id = next(self._idc)
    return Base

然后我使用工厂类创建孩子:

class A(basefactory()):
    def __init__(self):
        super().__init__()

class B(basefactory()):
    def __init__(self):
        super().__init__()

如何测试 AB 是否是工厂类创建的类的子类?
如果没有工厂类,我会使用:issubclass(A, Base)),但当然这不适用于工厂类,因为 Base 未在全局空间中定义。

此设置的原因是我希望 AB 具有不同的 _idc 计数器,以便为子类的每个实例生成连续的 _ids。
如果AB 直接继承自Base,则共享计数器。让我用一个例子来说明我的意思。

使用上述工厂类设置,如果我这样做:

ll = [A(), A(), B(), B()]   
for e in ll:
    print(e._id, end=", ")

它打印:0, 1, 0, 1, 。相反,如果我将Base 移动到全局空间中并且AB 直接从Base 继承,则前面的代码将打印:0, 1, 2, 3,

我希望_id0, 1, 0, 1, ,这就是我使用工厂类设置的原因。 在我的真实案例中,我不仅有 AB(我有 10 个由工厂类创建的类,将来可能会增加),所以我不想重复自己并初始化每个类中的计数器孩子。

但是我还需要断言一个类是否是Base 的子类,或者换句话说,如果它是通过工厂类创建的。这就是问题所在。是否可以使用issubclass 检查类层次结构?或者我需要更改设置或使用 cmets 中建议的解决方法?

关于建议的副本

我不认为是 Understanding Python super() with __init__() methods 的重复项。我知道super 做了什么,并且在这种特定情况下没有用。我希望每个子类都有一个不同的计数器,我看不出引用父类有什么帮助。
也许它有帮助(如果有,请发布答案),但由于建议的副本不涉及工厂类,我认为这个问题仍然不同。

【问题讨论】:

  • 简而言之,你没有。您必须保存对制造类的引用以进行比较。您应该研究 __new__ 来实现您的计数器,而不是您当前的方法。
  • 这是一个很难回答的问题,因为您当前的设置无法做到这一点,而且有很多不同的方法可以让它工作......您可以使用元类,或者你可以让 Base 从另一个类继承,或者你可以重写 Base 以便它分别计算每个子类的实例,等等。
  • 请记住AB共享一个基类;它们每个都有一个不同的基数,而这两个基数恰好有相同的名称。是否有任何理由重复创建不同但相同的类?
  • @chepner 我编辑我的问题以更好地解释情况,希望现在更清楚

标签: python factory


【解决方案1】:

我认为装饰器会做你想做的事(向类添加实例计数器),而不是生成不必要的基类的工厂函数。

from itertools import count

def add_counter(cls):
    cls._idc = count(0)
    old_init = cls.__init__
    def __init__(self, *args, **kwargs):
        old_init(self, *args, **kwargs)
        self._id  = next(self._idc)
    cls.__init__ = __init__
    return cls

@add_counter
class A:
    pass

@add_counter
class B:
    pass

ll = [A(), A(), B(), B()]
for e in ll:
    print(e._id, end=", ")

【讨论】:

    【解决方案2】:

    好吧,我不知道如何正确访问这些信息,但是当输入 help(A) 时,你会得到 Base

    Help on class A in module __main__:
    class A(Base)
     |  Method resolution order:
     |      A
     |      Base
     |      builtins.object
     |  
     |  Methods inherited from Base:
     |  
     |  __init__(self)
     |  
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from Base:
     |  
     |  __dict__
     |      dictionary for instance variables (if defined)
     |  
     |  __weakref__
     |      list of weak references to the object (if defined)
    

    我知道它必须可以正确访问它

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-19
      • 1970-01-01
      • 2012-02-15
      • 1970-01-01
      • 2013-06-13
      相关资源
      最近更新 更多