4

我有一个类父类和两个子类 child1(parent) 和 child2(parent) 有点像下面的近代码。(编辑以更正确地显示父类正在做某事)

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']是什么。

4

2 回答 2

5

问题是在里面parent.__new__,你在调用child1(e),while调用child1.__new__,它找到实现parent.__new__并用相同的方法调用它e,它调用child1(e),它......所以你得到无限递归。

有更好的方法来设计这个,但如果你只是想修复你的设计,有三个选项:


如果您__new__在所有子类中定义,它不会通过parent.__new__. 您可以通过在andintermediate之间插入一个类来一步完成此操作,因此您只需要. 或者使用它们都继承的 mixin,或者……</p> parentchildNintermediate.__new__


摆脱继承。这里真的有什么理由child1parent

您似乎正在寻找在 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__onparent而不是其子类来捕获递归:

def __new__(cls, e):
    if cls is not parent:
        return super(parent, cls).__new__(cls)
于 2013-08-13T20:56:17.717 回答
3

如果您根本没有parent类,而只是一个普通功能,这会容易得多。

使用基类是语言中的一种模式,这是唯一真正做到这一点的方法。它在 Python 中没有必要也没有帮助。

于 2013-08-13T21:01:27.573 回答