【问题标题】:Creating custom class list in Python在 Python 中创建自定义类列表
【发布时间】:2015-03-24 22:46:08
【问题描述】:

我正在尝试创建一个自定义列表子类,它继承列表类的所有方面,除了它的append 方法在每次添加新对象时对列表进行排序。

到目前为止,我有这样的事情:

class CommentList(list):
    def append(self, other):
         return self.data_list.append(other)

我不确定如何为此引入排序功能以及如何改进上述方法。

【问题讨论】:

  • 这里很好地解释了为什么你不应该从列表中继承 stackoverflow.com/questions/21692193/why-not-inherit-from-listt
  • @Andrey:这是一个 C# 解释。此外,我不清楚接受的答案是否适用于 OP 的问题。无论如何,告诉 OP 从collections.abc.MutableSequence 继承而不是仅仅说“不要那样做”会更有用。
  • @Andrey,这种情况与那种情况不符。这里 OP 希望扩展 List 的功能以使其保持排序;结果仍然是一个列表。对于这种情况,List 是否是正确的基类是另一个问题,Kevin 可能是对的(尽管我不熟悉他提到的类)
  • @Kevin 的解释是抽象的,对 C# 的细节很少。从 list/List/MutableSequence 继承业务逻辑类通常是个坏主意。仅当您要实现某种新型容器时才有意义。组合优于继承。
  • 此外,从MutableSequence继承业务逻辑类是重点;它是 IList 的 Python 等价物,除了它具有大多数方法的默认实现。

标签: python list class


【解决方案1】:

最简单的可能实现是:

class CommentList(list):

    def append(self, val):
        super(CommentList, self).append(val)
        self.sort()

这就是你想要的:

>>> l = CommentList((2, 3, 4))
>>> l.append(5)
>>> l
[2, 3, 4, 5]
>>> l.append(1)
>>> l
[1, 2, 3, 4, 5]

但请注意,还有其他方法可以将数据放入列表中(__add__extend__setitem__);他们应该涉及排序吗?应该例如一片CommentList 是另一个CommentList,还是香草listCommentList 看起来就像一个普通列表,因为它继承了 __repr__,但这可能会产生误导。子类化内置类型可能很复杂;你真的应该从MutableSequence abstract base class 开始,而不是。

【讨论】:

    【解决方案2】:

    只需使用超级调用,然后添加您的排序函数调用:

    class CommentList(list):
        def append(self, other):
    
            # call the append of the parent class
            # which of course is the builtin list
    
            super(CommentList, self).append(other)
    
            # then call the sort method that we 
            # just inherited from the parent 
    
            self.sort() # sort after using append
    

    【讨论】:

      【解决方案3】:
      class CommentList(list):
          def append(self, other):
               r = super(CommentList, self).append(other)
               self.sort()
               return r
      

      【讨论】:

      • 没有提到退货。
      • @MalikBrahimi - 通常是一个好习惯,即在默认情况下覆盖方法时返回超类返回的任何内容。目前 append 返回 None 并且此行为是继承的。如果由于任何不可预见的原因,append 的返回行为在 Python 的未来版本中发生了变化,则此代码将继承这种变化。
      【解决方案4】:

      在我看来,这样做会很“不合常规”。没有理由使用继承,您可以简单地在每次追加后返回一个排序列表。

      也就是说,在列表填满之前,通常不需要对列表进行排序。在这种情况下,构建您的列表,然后通过将 sorted(original_list) 分配给它来设置一个 sorted_list。

      在任何一种情况下,您都必须确定对列表进行排序意味着什么。

      您还必须担心如何处理:

      a = list () a.append (19) a.append ('my birthday')

      【讨论】:

        【解决方案5】:

        您可以这样做,但几乎可以肯定这不是您想要的。除其他原因外,append() 只是列表元素更改的一种方式。例如 setitem()、insert() 和 extend()。如果您希望“列表已排序”成为不变量,则需要覆盖所有这些方法。您可能不打算使用这些方法。如果是这样,您可以只创建一个包含列表的对象,并且只公开您想要的方法。

        如果性能是一个问题,您可能希望更改为直接支持维护排序顺序的堆或树等数据结构。

        如果您真的想要一个像列表一样工作但具有附加触发排序的额外功能的对象,那么您所拥有的将起作用,但这是一种奇怪的行为。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-06-23
          • 1970-01-01
          • 2020-08-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-08-28
          相关资源
          最近更新 更多