2012-02-24 55 views
14

我想一些屬性添加到內置list類型,所以我寫了這個:Python:我如何從內置列表類型繼承?

class MyList(list): 
    def __new__(cls, *args, **kwargs): 
     obj = super(MyList, cls).__new__(cls, *args, **kwargs) 
     obj.append('FirstMen') 
     return obj 

    def __init__(self, *args, **kwargs): 
     self.name = 'Westeros' 

    def king(self): 
     print 'IronThrone' 

if __name__ == '__main__': 
    my_list = MyList([1, 2, 3, 4]) 
    print my_list 

my_list只包含元素'FirstMen'。爲什麼我的__new__在這裏不起作用?我應該如何繼承像list這樣的內置類型?像str這樣的不可變類型是不是一樣?

+0

參見[這個問題](http://stackoverflow.com/questions/3945940/what-to-consider-before-subclassing-list)有關子類列表主題的討論,以及它如何往往不是你想要的。 (collections.MutableSequence,如果可用,可能是更好的路線:閱讀[Alex Martelli](http://stackoverflow.com/a/3488283/487339))。 – DSM 2012-02-24 15:12:17

+0

可能的重複:http://stackoverflow.com/q/4093029/596361 – 2012-10-02 15:52:28

回答

19

list類型通常在其__init__()方法內對列表進行實際初始化,因爲它是可變類型的約定。子類型不可變類型時,只需要覆蓋__new__()。雖然你可以覆蓋__new__()當子類化列表時,你的用例沒有太多的意義。它更容易只是簡單地覆蓋__init__()

class MyList(list): 
    def __init__(self, *args): 
     list.__init__(self, *args) 
     self.append('FirstMen') 
     self.name = 'Westeros' 

另外請注意,我建議不要在這種情況下使用super()。你想在這裏打電話list.__init__(),而不是其他任何東西。

+0

啊,我忘了調用超類的'__init__'。但是不可變類型呢?或者是否有關於何時應該覆蓋__new__的一般規則? – 2012-02-24 15:07:32

+0

@ PJ.Hades:只有在需要時才覆蓋它。如果您需要影響不可變數據的構建,通常情況下就是這種情況。繼承'tuple'來添加更多的方法和屬性不需要覆蓋'__new __()'。如果有疑問,請閱讀文檔。 – 2012-02-24 15:09:49

+0

@SvenMarnach,'self.append('FirstMen')' - FirstMen'追加到'list'或'MyList'的位置? – 2018-01-08 13:53:02

8

首先,你是否在做這個練習來理解__new__?如果沒有,那麼幾乎可以肯定有更好的方法來做你想做的事情。你能解釋一下你想在這裏做什麼嗎?

這就是說,這裏是正在發生的事情在你的榜樣:

  1. 您調用MyList([1,2,3,4])
  2. 這首先調用MyList.__new__(MyList,[1,2,3,4])
  3. 你實現調用list.__new__(MyList,[1,2,3,4]) 這將返回的MyList一個新的實例,沒有元素。 list.__new__不填充列表。它留給list.__init__,這是永遠不會被調用。
  4. 您的__new__方法將'FirstMen'附加到空的MyList實例。
  5. 您的__new__方法返回MyList的實例。
  6. MyList.__init__([1,2,3,4])被調用。
  7. 它將name屬性設置爲'Westeros'
  8. 它返回。
  9. 該實例被分配到my_list並打印。

在這裏看到的__new__的解釋:對於一些http://docs.python.org/reference/datamodel.html#basic-customization

+0

我知道這個問題的原因。感謝您的解釋:) – 2012-02-24 15:18:43

+0

請注意,如果'MyList .__ init __()'*調用了'list .__ init __()',它會用'[1,2,3,4]'替換列表的內容,所以「FirstMen」將會消失。 – 2012-02-24 16:42:27