4

我有一個類Parent。我想爲Parent定義一個__new__,所以它在實例化時會有一些魔力(爲什麼,請參閱腳註)。我也希望子類從這個類和其他類繼承來獲得父類的特性。 Parent__new__將返回子類的基類和Parent類的子類的實例。Python多重繼承:哪個__new__調用?

這是怎樣的子類將被定義:

class Child(Parent, list): 
    pass 

但現在我不知道該怎麼__new__Parent__new__調用。如果我打電話object.__new__,上面的Child示例抱怨應該調用list.__new__。但Parent怎麼知道?我做了工作,所以它遍歷所有__bases__,並調用每個__new__一個try:塊中:

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__魔術等)的子類的對象的理由。 I could have done this in __init__,但如果新類具有不同的內部結構,則無法修改self.__class____init__),這是由於多重繼承造成的。
+0

我有一個答案,但後來我意識到我完全誤解了你的問題,所以我刪除了它,然後修改它並取消刪除它。我認爲新的答案解決了你的問題,並將工作。我做了一些最小的測試。 – Omnifarious 2010-01-26 03:03:42

+0

你明顯地進入了元類編程領域,既棘手又奇妙。你使用__new__得到錯誤的原因是''object'和內建類型像'list'和'dict',以及'__slots__'對象都有不同的內存佈局。 更深入地瞭解你正在努力完成什麼將會有很大的幫助。您可能還想看看__metaclass__插槽中使用類裝飾器或函數。 – 2010-01-26 03:27:32

+0

我不知道你爲什麼需要修改自己的.__ class__,你沒有提到。如果你需要在__new__中這樣做複雜的魔術,一個解決方案往往更容易,根本不用它,而是使用工廠。 – 2010-01-26 05:59:18

回答

4

我想這會得到你想要的東西:

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

,你會不會需要bases關鍵字參數。除非我弄錯你的意圖,否則你會把它放在那裏。

+0

我認爲這是做到了。我之前嘗試過,不幸的是,我的代碼中有一些其他錯誤,導致它無法正常工作。 超級函數是一個神奇的子彈。 – 2010-01-27 05:48:55

+1

@Msoul,確實如此。說實話,我不知道爲什麼這是完全正確的,我只是想它會。 :-) – Omnifarious 2010-01-27 07:39:02