Python 多重继承:调用哪个 __new__?

4 投票
1 回答
3591 浏览
提问于 2025-04-15 18:28

我有一个叫做 Parent 的类。我想为这个类定义一个 __new__ 方法,这样在创建实例的时候可以做一些特别的事情(具体原因可以看脚注)。我还希望子类能够继承这个类的特性,以及其他类也能获得 Parent 的功能。Parent__new__ 方法会返回一个子类的实例,这个子类是基于子类的父类和 Parent 类的。

这是子类的定义方式:

class Child(Parent, list):
    pass

但是现在我不知道在 Parent__new__ 方法中应该调用哪个 __new__。如果我调用 object.__new__,上面的 Child 示例就会报错,提示应该调用 list.__new__。可是 Parent 怎么会知道呢?我让它循环遍历所有的 __bases__,并在 try: 块中调用每个 __new__

class Parent(object):
    def __new__(cls, *args, **kwargs):
        # There is a special wrapper function for instantiating instances of children
        # classes that passes in a 'bases' argument, which is the __bases__ of the
        # Children class.
        bases = kwargs.get('bases')
        if bases:
            cls = type('name', bases + (cls,), kwargs.get('attr', {}))
            for base in cls.__mro__:
                if base not in (cls, MyMainType):
                    try:
                        obj = base.__new__(cls)
                        break
                    except TypeError:
                        pass
            return obj
        return object.__new__(cls)

但这看起来就像是一种变通的方法。肯定有更好的办法来做到这一点吧?

谢谢。

  • 我想使用 __new__ 的原因是,我希望返回一个具有一些动态属性的子类对象(比如神奇的 __int__ 属性等)分配给这个类。我 本可以在 __init__ 中做到这一点,但如果新类有不同的内部结构,我就无法在 __init__ 中修改 self.__class__,而这里正是因为多重继承导致了这种情况。

1 个回答

4

我觉得这样做可以满足你的需求:

return super(Parent, cls).__new__(cls, *args, **kwargs)

而且你不需要使用 bases 这个关键词参数。除非我理解错了,你是故意把它放进去的。

撰写回答