For an introduction to slicing, please view the article How to Slice Lists/Arrays and Tuples in Python.
Slicing Your Own Python Objects
Alright, that's all cool, now we know how to slice. But how do we slice our own objects? If I implement an object that has a list, or custom data structure, how do I make it slicable?
First, we define our custom data structure class.
[python]
from collections import Sequence
class MyStructure(Sequence):
def __init__(self):
self.data = []
def __len__(self):
return len(self.data)
def append(self, item):
self.data.append(item)
def remove(self, item):
self.data.remove(item)
def __repr__(self):
return str(self.data)
def __getitem__(self, sliced):
return self.data[sliced]
[/python]
Here, we declare a class with a list as the back-end of our structure. MyStructure
doesn't really do that much, but you can add, remove, and get items from it, so it's still useful in a sense. The only method we need to pay attention to in particular here is the __getitem__
method. This method is called whenever we try to get an item from our structure. When we call structure[0]
, this actually calls the __getitem__
method in the background and returns whatever that method returns. It's very useful when implementing a list style object.
Let's create our custom object, add an item to it, and try to get it.
[python]
>>> m = MyStructure()
>>> m.append('First element')
>>> print(m[0])
First element
[/python]
Yes! We did it! We assigned our element, and properly got it back. Nice. Now for the slicing part!
[python]
>>> m.append('Second element')
>>> m.append('Third element')
>>> m
['First element', 'Second element', 'Third element']
>>> m[1:3]
['Second element', 'Third element']
[/python]
Awesome! We basically get all the slicing for free because of using list
's functionality.
That's pretty amazing. Python is amazing. How about something a little more complex? What about using a dictionary as our main data structure?
Alright. Let's define another class for using a dictionary.
[python]
class MyDictStructure(Sequence):
def __init__(self):
# New dictionary this time
self.data = {}
def __len__(self):
return len(self.data)
def append(self, item):
self.data[len(self)] = item
def remove(self, item):
if item in self.data.values():
del self.data[item]
def __repr__(self):
return str(self.data)
def __getitem__(self, sliced):
slicedkeys = self.data.keys()[sliced]
data = {k: self.data[k] for key in slicedkeys}
return data
[/python]
Ok, so what are we doing here? Basically the same stuff that we did in the MyStructure
, but this time we're using a dictionary as our main structure, and the __getitem__
method definition has changed. Let me explain what changed in __getitem__
.
First, we get the slice
object that is passed in to __getitem__
and use it to slice the dictionary's key values. Then, using dictionary comprehension, we put all of the sliced keys and values into a new dictionary using our sliced keys. This gives us a nice sliced dictionary that we can use for whatever we like.
Here it is in action:
[python]
>>> m = MyDictStructure()
>>> m.append('First element')
>>> m.append('Second element')
>>> m.append('Third element')
>>> m
{0: 'First element', 1: 'Second element', 2: 'Third element'}
>>> # slicing
>>> m[1:3]
{1: 'Second element', 2: 'Third element'}
[/python]
And that's it. Simple, elegant, and powerful.
If you want to know how to slice strings, that's covered in another article titled How to Get a Sub-string From a String in Python – Slicing Strings.
That's all for now. Hope you enjoyed learning about slicing and I hope it will assist you in your quest.
Peace out.