【问题标题】:Python multiple inheritance: which __new__ to call?Python 多重继承:调用哪个 __new__?
【发布时间】:2010-01-26 02:18:39
【问题描述】:

我有一堂课Parent。我想为Parent 定义一个__new__,所以它在实例化时会产生一些魔力(原因见脚注)。我还希望子类从这个类和其他类继承以获取父类的功能。 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__ 属性等)。我could have done this in __init__,但是如果新类具有不同的内部结构,我将无法修改__init__ 中的self.__class__,这是由于多重继承造成的。

【问题讨论】:

  • 我有一个答案,但后来我意识到我完全误解了你的问题,所以我删除了它,然后修改它并取消删除它。我认为新答案可以解决您的问题并且会起作用。我做了一些最小的测试。
  • 您显然进入了元类编程领域,既棘手又奇妙。 new 出现错误的原因是 object 和内置类型,如 listdict,以及带有 __slots__ 的对象都有不同的内存布局。更深入地了解您要完成的工作将大有帮助。您可能还想看看在 metaclass 槽中使用类装饰器或函数。
  • 我不确定你为什么需要修改 self.__class__,你没有提到这一点。如果您需要在 new 中执行此类复杂的魔法,通常更容易的一种解决方案是根本不执行此操作,而是使用工厂。

标签: python new-operator multiple-inheritance class-hierarchy


【解决方案1】:

我认为这会让你得到你想要的:

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

并且您不需要bases 关键字参数。除非我误会了你,而你是故意把它放在那里的。

【讨论】:

  • 我认为它做到了。我之前尝试过这个,不幸的是,我的代码中有一些其他错误阻止了它的工作。超级功能是一颗神奇的子弹。
  • @MTsoul,确实如此。老实说,我不知道为什么它确实有效,我只是认为它会。 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-25
  • 1970-01-01
  • 2017-11-25
  • 2020-12-18
相关资源
最近更新 更多