Reputation: 8072
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
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