【发布时间】: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__()
如何测试 A 或 B 是否是工厂类创建的类的子类?
如果没有工厂类,我会使用:issubclass(A, Base)),但当然这不适用于工厂类,因为 Base 未在全局空间中定义。
此设置的原因是我希望 A 和 B 具有不同的 _idc 计数器,以便为子类的每个实例生成连续的 _ids。
如果A 和B 直接继承自Base,则共享计数器。让我用一个例子来说明我的意思。
使用上述工厂类设置,如果我这样做:
ll = [A(), A(), B(), B()]
for e in ll:
print(e._id, end=", ")
它打印:0, 1, 0, 1, 。相反,如果我将Base 移动到全局空间中并且A 和B 直接从Base 继承,则前面的代码将打印:0, 1, 2, 3, 。
我希望_id 是0, 1, 0, 1, ,这就是我使用工厂类设置的原因。
在我的真实案例中,我不仅有 A 和 B(我有 10 个由工厂类创建的类,将来可能会增加),所以我不想重复自己并初始化每个类中的计数器孩子。
但是我还需要断言一个类是否是Base 的子类,或者换句话说,如果它是通过工厂类创建的。这就是问题所在。是否可以使用issubclass 检查类层次结构?或者我需要更改设置或使用 cmets 中建议的解决方法?
关于建议的副本
我不认为是 Understanding Python super() with __init__() methods 的重复项。我知道super 做了什么,并且在这种特定情况下没有用。我希望每个子类都有一个不同的计数器,我看不出引用父类有什么帮助。
也许它有帮助(如果有,请发布答案),但由于建议的副本不涉及工厂类,我认为这个问题仍然不同。
【问题讨论】:
-
简而言之,你没有。您必须保存对制造类的引用以进行比较。您应该研究
__new__来实现您的计数器,而不是您当前的方法。 -
这是一个很难回答的问题,因为您当前的设置无法做到这一点,而且有很多不同的方法可以让它工作......您可以使用元类,或者你可以让
Base从另一个类继承,或者你可以重写Base以便它分别计算每个子类的实例,等等。 -
请记住
A和B不共享一个基类;它们每个都有一个不同的基数,而这两个基数恰好有相同的名称。是否有任何理由重复创建不同但相同的类? -
@chepner 我编辑我的问题以更好地解释情况,希望现在更清楚