我有一个类父类和两个子类child1(父类)和child2(父类)类似于以下代码。 (编辑为更准确地表明父类正在做某事)
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']
的值。
答案 0 :(得分:3)
问题是在parent.__new__
内部,您正在调用child1(e)
,同时调用child1.__new__
,它会在parent.__new__
中找到实现并使用相同的{{e
调用它1}},它调用child1(e)
,这......你得到无限递归。
有更好的方法来设计它,但如果您只想修改设计,有三种选择:
如果您在所有子类中定义__new__
,则不会通过parent.__new__
。您可以在intermediate
和parent
之间插入childN
课程,只需一步即可完成此操作,因此您只需要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
和朋友。
最后,您只需处理__new__
上的parent
而不是其子类来捕获递归:
def __new__(cls, e):
if cls is not parent:
return super(parent, cls).__new__(cls)
答案 1 :(得分:3)
如果你没有parent
成为一个类,只是一个正常的函数,这会容易得多。
使用基类是一种语言模式,这是实现这一目标的唯一方法。它在Python中没有必要或没有帮助。