【问题标题】:Python: Right way to extend listPython:扩展列表的正确方法
【发布时间】:2014-01-17 22:12:27
【问题描述】:

我想扩展“列表”类的功能并为事件添加自定义处理程序:“将新项目添加到列表”和“从列表中删除项目”。对于这个任务,我不想使用组合,最好是继承。

我尝试做什么:

class ExtendedList(list):

    def append(self, obj):
        super(ExtendedList, self).append(obj)
        print('Added new item')

    def extend(self, collection):
        if (hasattr(collection, '__iter__') or hasattr(collection, '__getitem__')) and len(collection)>0:
            for item in collection:
                self.append(item)

    def insert(self, index, obj):
        super(ExtendedList, self).insert(index, obj)
        print('Added new item')

    def remove(self, value):
        super(ExtendedList, self).remove(value)
        print('Item removed')

但它不能正常工作。我无法捕获所有添加和删除事件。例如:

collection = ExtendedList()
collection.append('First item')
# Out: "Added new item\n"; collection now is: ['First item']
collection.extend(['Second item', 'Third item'])
# Out: "Added new item\nAdded new item\n"; collection now is: ['First item', 'Second item', 'Third item']
collection += ['Four item']
# Don't out anythink; collection now is: ['First item', 'Second item', 'Third item', 'Four item']
collection.remove('First item')
# Out: "Item removed\n"; collection now is: ['Second item', 'Third item', 'Four item']
del collection[0:2]
# Don't out anythink; collection now is: ['Four item']
collection *= 3
# Don't out anythink; collection now is: ['Four item', 'Four item', 'Four item']

根据我的情况扩展类“列表”的正确方法是什么?感谢您的帮助。

【问题讨论】:

  • 在这里定义列表的子类不是一个好主意。相反,您应该更喜欢聚合而不是继承
  • 每个都做不同的事情,所以使用更适合您想要完成的事情的那个?
  • 您已经展示了会发生什么,但它有什么问题?你想发生什么?
  • 您的问题是“对于这项任务,我不想使用组合,最好是继承。”为什么?一般来说,对于这样的任务来说,情况并非如此。如果你的任务有一些具体的东西使它成为现实,那么知道那个具体的东西可能意味着人们可以写出更好的答案。 (或者,如果你错了,人们可以解释为什么组合和授权对你的具体情况仍然有意义。)
  • @uzumaxy:如果您是从另一种语言开始使用 Python,尤其是 Java 或另一种执行 OO 旧 C++ 风格的语言,那么这是非常令人惊讶的事情之一。如果没有鸭子类型,继承是创建像另一种类型的实例一样的对象的唯一方法。使用鸭子打字,这只是一种方式,而且通常不是最好的方式。

标签: python list inheritance


【解决方案1】:

与其从list 本身继承,不如从其抽象基类collections.MutableSequence 继承。这为您完成了所有基本工作,让您专注于您想要更改的内容。有一个关于 ABC 的好问题here

【讨论】:

    【解决方案2】:

    *=+=del 等操作是使用 list 类的运算符函数实现的,例如 __add____delitem____delslice__ 等。它们有很多。如果您想拦截对“扩展”列表类的所有可能调用,则需要覆盖大部分(如果不是全部)这些运算符。

    由于您无法控制内置类的实现方式,因此围绕内置类组合一个新类通常比从内置类继承更容易。

    【讨论】:

    • 看来,我错了,最好使用聚合或从 MutableSequence 继承...
    【解决方案3】:

    如果您想覆盖 + 等运算符,您需要明确地执行此操作。 The documentation 将帮助您找出需要更改的内容。

    【讨论】:

      【解决方案4】:

      看看类UserList:http://pydoc.org/2.2.3/UserList.html 它显示了您需要更改的所有方法。 一个问题是type(ExtendedList([]) * 2) == list

      【讨论】:

      • 这是一个非常过时的答案。 Python 2.2+ 扩展 list 没有问题,“问题”从 2.3 开始就有了解决方案,而 2.6+ 有 MutableSequence ABC,消除了任何人再次查看 UserList 的最后一个原因,这就是为什么它已被弃用并完全从文档中删除。
      • 对。现在已经过时了。只是不记得 MutableSequence。
      • 对不起,它在 3.0 中被删除,而不是 2.6。 2.6 将它和the other related obsolete modules 塞进一个页面,每隔几句话就会提醒您“注意:此模块仅用于向后兼容”。不过,这不是一个好建议。特别是对于一个看起来像是在使用 Python 3.x 的 OP。
      猜你喜欢
      • 1970-01-01
      • 2022-01-08
      • 1970-01-01
      • 2011-05-28
      • 2012-05-28
      • 1970-01-01
      • 2012-01-28
      • 2018-09-24
      • 1970-01-01
      相关资源
      最近更新 更多