【问题标题】:Extend list class with inplace slicing使用就地切片扩展列表类
【发布时间】:2018-07-27 20:58:11
【问题描述】:

我正在尝试编写一个继承自 Python list 类的类,并且有一个方法可以进行就地切片(修改了原始对象)。

这就是我所拥有的:

class MyList(list):
    def __init__(self, mylist = []):
        list.__init__(self)
        self.extend(mylist)
    def slice_it(self, x):
        self = self[:x]
        return self

然后我实例化它:

>>> mylist = MyList(mylist=[1,2,3,4,5])
>>> mylist
[1, 2, 3, 4, 5]
>>> mylist.slice_it(3)
[1, 2, 3]
>>> mylist
[1, 2, 3, 4, 5]

我希望最后一个输出是 [1, 2, 3]。有什么想法吗?

【问题讨论】:

  • 分配给self只是分配一个局部变量;像任何其他变量赋值一样,它不会改变你的对象。
  • @user2357112 我知道,但这是我能做的最好的。我也尝试不使用该行,但直接使用return self[:x]。得到了同样的结果。
  • 如果你没有编写MyList 类,而你只是有一个列表你想改变以产生你想要的最终状态,你会写什么代码来做到这一点?将该代码写入slice_it
  • 我认为在 Python 中就地修改列表不是一个好主意,无论是从便利性还是性能方面。
  • @liliscent 我不知道,在某些情况下它可能非常方便/高效。我不知道我是否会简单地将list 子类化以添加一个执行此操作的方法,但我怀疑 OP 坚持使用某种流畅的接口。

标签: python list class inheritance


【解决方案1】:

您只是分配给局部变量self,这不会改变列表。你必须使用一个mutator方法,所以试试:

class MyList(list):
    def __init__(self, mylist = None):
        list.__init__(self)
        if mylist is not None:
            self.extend(mylist)
    def slice_it(self, x):
        self[:] = self[:x]
        return self

在行动:

In [10]: mylist = MyList(mylist=[1,2,3,4,5])

In [11]: mylist
Out[11]: [1, 2, 3, 4, 5]

In [12]: mylist.slice_it(3)
Out[12]: [1, 2, 3]

In [13]: mylist
Out[13]: [1, 2, 3]

请注意,您实际上可以使用切片符号来完成这项工作:

In [30]: from itertools import islice
    ...: class MyList(list):
    ...:     def __init__(self, mylist = []):
    ...:         list.__init__(self)
    ...:         self.extend(mylist)
    ...:     def __getitem__(self, x):
    ...:         if isinstance(x, slice):
    ...:             self[:] = islice(self, x.start, x.stop, x.step)
    ...:             return self
    ...:         else:
    ...:             return list.__getitem__(self, x)
    ...:

In [31]: mylist = MyList(mylist=range(20))

In [32]: mylist[::2]
Out[32]: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

In [33]: mylist
Out[33]: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

In [34]: mylist[0]
Out[34]: 0

In [35]: mylist
Out[35]: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

流畅的界面怎么样?

In [36]: mylist = MyList(mylist=range(100))

In [37]: mylist[::2][:10]
Out[37]: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

In [38]: mylist
Out[38]: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

【讨论】:

  • @DeliriousLettuce 当然可以,尤其是在您不了解默认参数语义的情况下。老实说,我什至没有注意到它,我只是从 OP 中复制的,尽管在这种情况下,它可能还不错,因为它实际上从未在 __init__ 中发生突变,但仍然可能最好安全,不要使用。
  • @DeliriousLettuce 不用删,大家看到这些cmets就好了。编辑哦,好吧,太晚了:)
猜你喜欢
  • 1970-01-01
  • 2019-10-01
  • 1970-01-01
  • 2019-10-22
  • 1970-01-01
  • 2023-04-07
  • 2016-12-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多