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

Building Generic Protocols

00:00 Protocols are a pretty flexible way of defining behaviors. Hopefully you’ve understood that by now, but you can create even more flexible protocols if you combine protocols with generics.

00:12 So in this lesson, you learn how to build generic protocols. And remember that generics or generic classes allow you to parameterize the types of methods and attributes in your class.

00:25 You’re allowed to relate them across different methods, across different attributes, and you’re allowed to preserve this information throughout your program.

00:34 For example, static type checkers will treat a list of integers differently from a list of strings, because static type checkers know that if you remove an element from a list of integer, you are receiving an integer, not a string.

00:49 So that’s the point of generics. And protocols are supposed to define behaviors that you care about, so therefore, if you put them together, generic protocols allow you to create these parametrized behaviors.

01:00 So you get the behaviors, but you’re also allowed to parameterize their types to create more structure, to preserve more information about your program and its types. To see this in code, go ahead and open an empty file, for example, mysequence.py.

01:19 Once you have a new file open, go ahead and create a my_list variable without actually creating it. Just say it exists and type it as a list of integer.

01:31 If you then ask for the type of the first element of said list, static type checkers will tell you it’s an integer. So go ahead and open your terminal,

01:43 run mypy on your file, and you will see a note saying that the revealed type is builtins.int. What the static type check is telling you is that the type of the first element of my_list will be of type integer, precisely because the list is a list of integers.

02:00 Now the list type is a generic, you parameterize it with integer, and then Python will know that when you index into the list, you get elements of the same type of the list’s type.

02:14 That’s the whole point of lists. You keep elements in there, and when you get them back, you get them back. So how could you implement something like this as your own protocol?

02:23 How could you create this type of behavior? So go ahead, close the terminal and delete all of this code, and start by importing Protocol from the module typing.

02:35 Then what you’ll do is you’ll create a class that you can call MySequence, and this is a protocol, so it must inherit from Protocol, but this will also be a generic class.

02:46 Therefore, you need to pass it a type variable. If you’re running Python 3.11 or earlier, then this specific syntax for the type variable T will not work.

02:58 So be mindful of that. So you create a generic class that inherits from Protocol, and then you can define method signatures

03:08 as per usual, both as you’re used to do for your generics and for your protocols. You’re just doing both at the same time. For example, you could say that the __getitem__() method will take self and then it’ll accept an index that’s an integer, and it’s going to return an element of type T, which is the parametrized type for your protocol.

03:31 Again, because this is a protocol, you don’t need to implement the method itself,

03:36 and then just make sure this is working. What you can go ahead and do is create a my_sequence variable or declare it as satisfying the protocol, MySequence with, for example, the type str strings.

03:50 And then you can ask your type checker to reveal the type of the first element of your sequence. And if everything goes well, your static type checker will tell you that it’s a str, a string.

04:03 So go ahead, open your terminal.

04:06 If you run your static type checker on your file, mysequence.py, you should get a note saying that the reveal type is str, a string, and the only reason the static type checker was able to tell you that is because your protocol is generic over type T, which is returned from your dunder method __getitem__().

04:26 Therefore, when you index into the sequence, you get values of that parameterized type. So this is how you can build a generic protocol.

04:37 Now, you might be wondering, okay, I can create generic protocols, but what’s the point? Well, Python has a couple of concepts that you can think of as generic protocols.

04:50 I will give you two examples of generic protocols that are grounded in the way Python works. For example, and we’ve seen this one already. This was the inspiration for the code we just looked at.

05:04 Sequences are generic over the type of the elements they contain. For example, a list of strings is, I just said it, it’s a list of strings. When you give an index to the list, you get the string back.

05:19 So the T in the slide represents the type of whatever is contained inside the sequence. For example, a list of strings will be a sequence of strings.

05:29 Strings themselves are sequences of the characters, which are also strings. There’s plenty of different sequences in Python. And another example would be mappings, which is the general way of referring to things like dictionaries, which typically are generic over the types of the keys and the values.

05:48 For example, a configuration file might have a mapping whose values are Booleans for configuration settings that are turned on or off. And the keys are strings, which are the names of the configurations.

06:03 So mappings are generic over these two types. If you provide the key of the correct type, and if the key exists, you get a value of the correct type. So these are just two examples of generic protocols.

06:17 Up until this point, you’ve only created protocols that specify methods that must be implemented. But in the next lesson, you will see that you can even have more flexibility than that.

06:27 So stay tuned.

Become a Member to join the conversation.