Python:如何从内置列表类型继承?

发布于 2025-01-08 10:32:09 字数 615 浏览 3 评论 0原文

我想向内置 list 类型添加一些属性,所以我这样写:

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 这样的不可变类型也是一样吗?

I want to add some attributes to the built-in list type, so I wrote this:

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

but my_list contains only the element 'FirstMen'. Why my __new__ doesn't work here? And how should I inherit from a built-in type like list? Is it the same for the immutable types like str?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

慵挽 2025-01-15 10:32:09

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__(),而不是其他任何内容。

The list type usually does the actual initialisation of the list inside its __init__() method, as it is the convention for mutable types. You only need to overwrite __new__() when subtyping immutable types. While you can overwrite __new__() when subclassing list, there is not much point in doing so for your use case. It's easier to just overwrite __init__():

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

Also note that I recommend against using super() in this case. You want to call list.__init__() here, and not possibly anything else.

十雾 2025-01-15 10:32:09

首先,您这样做是为了理解 __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

First of all, are you doing this as an exercise to understand __new__? If not, there is almost certainly a better way to do what you're trying to do. Could you explain what you'd like to achieve here?

That said, here's what's happening in your example:

  1. You invoke MyList([1,2,3,4])
  2. This first invokes MyList.__new__(MyList,[1,2,3,4])
  3. Your implementation calls list.__new__(MyList,[1,2,3,4])
    This returns a new instance of MyList, with no elements. list.__new__ does not populate the list. It leaves that to list.__init__, which is never called.
  4. Your __new__ method appends 'FirstMen' to the empty MyList instance.
  5. Your __new__ method returns the instance of MyList.
  6. MyList.__init__([1,2,3,4]) is invoked.
  7. It sets the name attribute to 'Westeros'.
  8. It returns.
  9. The instance is assigned to my_list and printed.

See here for an explanation of __new__: http://docs.python.org/reference/datamodel.html#basic-customization

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文