Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Implementing Custom Sequences and Mappings

00:00 Let’s go ahead and create a custom sequence that behaves like a list but is immutable.

00:08 Let’s start by defining a new class called ImmutableList. This class is going to act like a list, but it won’t allow any changes to its content once it’s created.

00:21 class ImmutableList: You’ll need to initialize the object with the .__init__() method. You’ll take whatever data is passed in, which is going to be an interable, like a list and store it as a tuple in the _data attribute.

00:40 And the tuple is used here because it’s immutable, meaning it can’t be changed, which is exactly what you need for an immutable list. def __init__( self, iterable): and the iterable that you’ll be getting, colon.

00:57 self._data equal calling the tuple function and then passing in the iterable that you’ll be getting. Now you might be wondering what is this _data here?

01:13 The use of _data as the attribute name follows a common Python convention where a single underscore at the beginning of a variable name indicates that this is intended to be a private or internal attribute.

01:30 It’s sort of a way of saying, Hey, this is for internal use only, so be careful if you choose to interact with it directly.

01:38 Now you’ll need to add the .__getitem__() magic method. This lets you access items in your immutable list using indexing just like you would with a regular list.

01:51 For example, if you would want the third item, you’ll simply use immutable_list[2]. Passing in self, and also the index that you’ll be getting, colon, and you’ll be returning self dot accessing the tuple _data square brackets, the index that you’ll be asked.

02:17 Now you’ll implement the .__len__() magic method. You already know how it works. The len() method allows you to get the length of the list by calling len() and then the immutable list.

02:30 This will return the number of items in the _data tuple passing in self, and then returning len() and self._data.

02:45 That was a typo. You’ll also need to include the .__contains__() magic method. This method is triggered when you use the in keyword or not in keyword to check if an item exists in the list, passing in self and the item you’ll be checking and your return item in self ._data.

03:13 So this will return True if you can find the item in your tuple and False if not. The only thing left is the .__reversed__() magic method, which lets you reverse the list using the reversed() built-in function.

03:32 It returns a new immutable list with the items in reverse order,

03:38 and then you’ll be returning a new immutable list object, but reversed this time and you’ll be passing self._data.

03:54 These are all the things that you need, but as you know, it’s best to have some sort of string representation. So let’s add the __repr__() or the represent method to give a string representation of your immutable list.

04:10 As you might remember, this is useful for debugging and seeing what’s inside the list. Let’s return “f” for format and class name first. So ImmutableList parentheses, and let’s just include the data in self ._data.

04:31 Okay, now your class is ready. So let’s create an instance. Let’s just call it immutable_list equal instantiating from Immutable List class, and let’s just give it some random numbers like 1, 2, 3, and 4.

04:56 Now let’s try to see if these methods that you just created actually work. So let’s start with len. Let’s print the len() function and then let’s give it the immutable_list object that you just created and see what happens.

05:17 Let’s run it. Okay, you get 4, which is exactly what you wanted to get because you passed in a list with four numbers in it. Now let’s comment this out so it doesn’t get printed again.

05:33 Now let’s try and see if you can access its elements using indexing, like a list, like for example, let’s say print(immutable_list and square brackets.

05:46 Let’s call the index 2, for example. You expect to get 3, so let’s see what happens.

05:55 And you do get 3, so it works. Now let’s comment this out and now let’s check if the membership implementation works. You implemented the .__contains__ magic method, so it should, let’s print for example (3 in immutable_list).

06:17 You expect to get 3 because you do have a 3. Let’s see, and you get True. Now, let’s change this to, for example, 8, which you don’t have and you expect to get False and you do get False.

06:31 So it works. Commenting this out. And finally, let’s see if reversed() works. Let’s say print and then let’s just call it the reversed built-in function and immutable list object. And there you go.

06:51 You get 4, 3, 2, 1, which is your initial immutable list reversed. Congratulations. You just created an immutable list class that behaves like a regular list, but with the added benefit of immutability.

07:10 By storing data in a tuple, you’ve ensured that the content of the list can’t be changed once it’s created, while still allowing all the familiar list operations like indexing, length, and checking membership, and even reversing the list.

07:30 Wait, we have to talk about something. So your immutable list mostly works and you tried it out and everything, but something about it isn’t a hundred percent correct.

07:41 Can you spot the problem here? You can look at these two code snippets and you can actually pause the video and think about it.

07:50 The problem here is that the .__repr__() magic method isn’t a hundred percent correct here. When you print out the reverse version or actually any version of the code, you get a tuple instead of a list, your input is a list so the representation of it should be a list too.

08:08 You’re just turning the data into a tuple internally to make sure that it’s immutable. How can we fix this? You could just turn self._data into a list in the .__repr__() method and then return it.

08:23 So that’s an option. Let’s go ahead and fix things.

08:27 Here is your ImmutableList class. Let’s pay attention to the .__repr__() method here. Let’s turn self._data into a list.

08:39 You can use the list() function, so list() here, and that should fix things. Let’s run the code.

08:53 So you’re printing reversed ImmutableList, so you should get ImmutableList, and then a list that says 4, 3, 2, 1. Let’s see if it worked.

09:06 And now you get ImmutableList, which is your class name, and then the reverse version of your input, which is 4, 3, 2, 1. You just fix the bug.

Become a Member to join the conversation.