我有一个父类和两个子类 child1(parent) 和 child2(parent),有点像下面的 near 代码。 (经过编辑以更恰本地表明父类正在做某事)
class parent(object):
name = None
def __init__(self,e):
# process the common attributes
name = e.attrib['name']
def __new__(cls,e):
if e.attrib['type'] == 'c1':
return child1(e)
elif e.attrib['type'] == 'c2':
return child2(e)
else:
raise
class child1(parent):
extra1 = None
def __init__(self,e):
super(e)
# set attributes from e that are specific to type c1
class child2(parent):
extra2 = None
def __init__(self,e):
super(e)
# set attributes from e that are specific to type c2
目标是能够根据参数的值得到“正确”的类。所以如果我可以说 obj = parent(element)
并且 obj
将是 child1
或 child2
取决于什么element.attrib['type']
的值是。
最佳答案
问题在于,在 parent.__new__
中,您正在调用 child1(e)
,同时调用 child1.__new__
,这会发现parent.__new__
中的实现,并使用相同的 e
调用它,它调用 child1(e)
,这......所以你得到无限递归。
有更好的设计方法,但如果您只想修复您的设计,有以下三种选择:
如果您在所有子类中都定义了 __new__
,它就不会落入 parent.__new__
。您可以通过在 parent
和 childN
之间插入一个 intermediate
类一步完成此操作,因此您只需要 intermediate.__new__
。或者使用一个他们都继承的mixin,或者……
摆脱继承。真的有任何理由 child1
是这里的 parent
吗?
你似乎在寻找 Smalltalk/ObjC 术语中称为“类集群”的东西,你不需要集群的“可见面”作为 Python 中的基类,就像你在那些语言。
例如:
class base(object):
pass
class parent(base):
def __new__(cls, e):
# same as before
class child1(base):
# etc.
在 Python 中,你甚至可以让 parent
成为一个 ABC,并用它register
每个 childN
这样你就可以使用 isinstance
和它的 friend 。
最后,您可以通过仅处理 parent
上的 __new__
而不是其子类来捕获递归:
def __new__(cls, e):
if cls is not parent:
return super(parent, cls).__new__(cls)
关于python - 如何从 __new__ 参数返回子类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18218876/