multigoodverse
multigoodverse

Reputation: 8072

Extend list class with inplace slicing

I am trying to write a class that inherits from the Python list class and has a method that does inplace slicing (original object modified).

This is what I have:

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

And then I instantiate it:

>>> 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]

I would expect the last output to be [1, 2, 3]. Any ideas?

Upvotes: 1

Views: 93

Answers (1)

juanpa.arrivillaga
juanpa.arrivillaga

Reputation: 95908

You are simply assigning to the local variable self, this won't mutate the list. You have to use a mutator method, so try:

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 action:

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]

Note, you can actually make this work with slice-notation:

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]

How's that for a fluent interface?

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]

Upvotes: 2

Related Questions