2012-02-24 51 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