【发布时间】: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和内置类型,如list和dict,以及带有__slots__的对象都有不同的内存布局。更深入地了解您要完成的工作将大有帮助。您可能还想看看在 metaclass 槽中使用类装饰器或函数。 -
我不确定你为什么需要修改 self.__class__,你没有提到这一点。如果您需要在 new 中执行此类复杂的魔法,通常更容易的一种解决方案是根本不执行此操作,而是使用工厂。
标签: python new-operator multiple-inheritance class-hierarchy