Python 工厂 class 继承
Python factory class inheritance
如何检查 class 是否是由工厂 class 创建的 parent 的 child?
考虑以下简单示例:
from itertools import count
def basefactory():
class Base:
_idc = count(0)
def __init__(self):
self._id = next(self._idc)
return Base
然后我使用工厂 class:
创建 children
class A(basefactory()):
def __init__(self):
super().__init__()
class B(basefactory()):
def __init__(self):
super().__init__()
我如何测试 A
或 B
是否是工厂 class 创建的 class 的 children?
如果没有工厂 class 我会使用:issubclass(A, Base))
但当然这不适用于工厂 class,因为 Base
没有在全局 [=89= 中定义].
此设置的原因是我希望 A
和 B
有不同的 _idc
计数器来为每个实例生成连续的 _id
s child classes.
如果 A
和 B
直接继承自 Base
,则计数器是共享的。让我用一个例子来说明我的意思。
使用上述工厂 class 设置,如果我这样做:
ll = [A(), A(), B(), B()]
for e in ll:
print(e._id, end=", ")
它打印:0, 1, 0, 1,
。相反,如果我在全局 space 和 A
和 B
中移动 Base
直接继承自 Base
,则先前的代码打印:0, 1, 2, 3,
.
我希望 _id
为 0, 1, 0, 1,
,这就是我使用原厂 class 设置的原因。
在我的真实情况下,我不只有 A
和 B
(我有 10 个 class 由工厂 class 创建,它们将来可能会增加),所以我不想重复自己并初始化每个 child.
中的计数器
但是我还需要断言 class 是否是 Base
的 child,或者换句话说,它是否是通过工厂 class 创建的。这就是问题所在。是否可以通过使用 issubclass
检查 class 层次结构来实现?或者我需要更改设置或使用评论中建议的解决方法?
关于提议的副本
我不认为是 Understanding Python super() with __init__
() methods 的副本。我知道 super
的作用,但在这种特定情况下没有用。我希望每个 child class 都有一个不同的计数器,我看不出引用 parent class 有什么帮助。
也许它有帮助(如果有,请 post 回答),但由于提议的副本不涉及工厂 classes,我认为这个问题仍然不同。
好吧,我不知道如何正确访问此信息,但是在键入 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)
我知道一定可以正常访问它
我认为装饰器会做你想做的事情(向 class 添加一个实例计数器),而不是生成不必要的基数的工厂函数 class.
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=", ")
如何检查 class 是否是由工厂 class 创建的 parent 的 child?
考虑以下简单示例:
from itertools import count
def basefactory():
class Base:
_idc = count(0)
def __init__(self):
self._id = next(self._idc)
return Base
然后我使用工厂 class:
创建 childrenclass A(basefactory()):
def __init__(self):
super().__init__()
class B(basefactory()):
def __init__(self):
super().__init__()
我如何测试 A
或 B
是否是工厂 class 创建的 class 的 children?
如果没有工厂 class 我会使用:issubclass(A, Base))
但当然这不适用于工厂 class,因为 Base
没有在全局 [=89= 中定义].
此设置的原因是我希望 A
和 B
有不同的 _idc
计数器来为每个实例生成连续的 _id
s child classes.
如果 A
和 B
直接继承自 Base
,则计数器是共享的。让我用一个例子来说明我的意思。
使用上述工厂 class 设置,如果我这样做:
ll = [A(), A(), B(), B()]
for e in ll:
print(e._id, end=", ")
它打印:0, 1, 0, 1,
。相反,如果我在全局 space 和 A
和 B
中移动 Base
直接继承自 Base
,则先前的代码打印:0, 1, 2, 3,
.
我希望 _id
为 0, 1, 0, 1,
,这就是我使用原厂 class 设置的原因。
在我的真实情况下,我不只有 A
和 B
(我有 10 个 class 由工厂 class 创建,它们将来可能会增加),所以我不想重复自己并初始化每个 child.
但是我还需要断言 class 是否是 Base
的 child,或者换句话说,它是否是通过工厂 class 创建的。这就是问题所在。是否可以通过使用 issubclass
检查 class 层次结构来实现?或者我需要更改设置或使用评论中建议的解决方法?
关于提议的副本
我不认为是 Understanding Python super() with __init__
() methods 的副本。我知道 super
的作用,但在这种特定情况下没有用。我希望每个 child class 都有一个不同的计数器,我看不出引用 parent class 有什么帮助。
也许它有帮助(如果有,请 post 回答),但由于提议的副本不涉及工厂 classes,我认为这个问题仍然不同。
好吧,我不知道如何正确访问此信息,但是在键入 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)
我知道一定可以正常访问它
我认为装饰器会做你想做的事情(向 class 添加一个实例计数器),而不是生成不必要的基数的工厂函数 class.
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=", ")