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

Duck Typing With Protocols

Resource linked in this lesson: Python Protocols: Leveraging Structural Subtyping

00:00 Now it’s time for something more Pythonic, namely protocols. So class inheritance that you have been using so far is very powerful, but it doesn’t work that well with the Pythonic idea of duck typing.

00:15 Now, to make static duck typing possible, you will need protocols. Now, duck typing and protocols, that might be new to you, so don’t worry about that. I’ve included a link to some excellent tutorials on protocols and duck typing.

00:29 But for now though, please remember that with protocols, you can define interchangeable classes as long as they share a common internal structure. So that means that you can enforce a relationship between classes without needing inheritance.

00:48 And that’s the difference. Now it’s that relationship that is called static duck typing, but for now it’s the avoidance of inheritance that’s interesting. So you’ll be implementing a protocol for your product classes.

01:02 So the first thing to do is to import Protocol. So therefore at the top of your code from typing

01:11 import Protocol, and that is with a capital P. And then please scroll down to your Product classes. So from lines 94 to 101, you have your abstract class, which is your SerializationProductBluePrint, and you have two abstract methods: start_object() and add_property().

01:32 So you are enforcing via inheritance the existence of those two methods in your child classes. Now you want to achieve the same thing with protocols, and this is how you implement that.

01:46 Now with protocols, there is no inheriting from an abstract base class. So the first thing to do is to remove that inheritance in your Product classes.

01:56 So line 104, remove that inheritance by deleting the parentheses and the words in between it.

02:04 Scroll down to line 118 and do the same thing for the _XMLSerializer class. Remove the inheritance from the abstract base class. And then just to point out on line 133, the _YAMLSerializer does not inherit from an abstract base class, it inherits from the _JSONSerializer and that inheritance still needs to remain.

02:29 If you then move back up to the top of the Product section, the next change I would make is cosmetic in nature really. I would change the name of the class there.

02:40 I would remove the word BluePrint on line 94 because this class will be a protocol and therefore it will not be inherited from anymore, so it’s not a blueprint in that sense.

02:55 Then it is no longer an abstract base class, it is a protocol. So inherit from Protocol. Protocol is with a capital P. The start_object() and the add_property() methods are no longer abstract methods, so you can remove the decorator on line 95 and on line 98.

03:18 But you do have to add, I suggest on line 101, the __str__() method.

03:30 So now you are almost done. With protocols, you have to be a little bit more specific about structure and the types. So line 95 start_object() adds that the first positional argument is object_name

03:49 and that that is going to be a string,

03:52 and object_id is going to be a string as well. And you also have to point out that this method start_object() method will return None.

04:04 And then, and this is new to me, behind the colon type space and three dots.

04:12 That means you can remove the word pass from line 96. For add_property() on line 97, you have to point out that that method will return None.

04:24 And then again, space and three dots behind the colon, and remove the word pass from line 98. And for the __str__() method that of course returns str, it’s kind of the point of its existence.

04:42 You then also add space and three dots on that same line behind the colon, and then remove the word pass from line 100.

04:53 And while you are here, there are actually some other improvements you can make to the code. In line 104, you define the current object, the tonal object, and in line 106 or line 107, you define this object to be a dictionary.

05:11 You might as well on line 104 define the attribute as a dictionary.

05:18 That is a small change. And the second change is looking at line 107, you can see that the start_object() method just adds an entry into the dictionary, which is exactly what the add_property() method does.

05:35 So you might as well from within start_object() call the add_ property() method to add the ID to the dictionary.

05:46 So line 107 can be replaced and you just write self. And then you use the .add_property() method. And the property you will add to your dictionary is id as in that’s id.

06:02 And the value without quotation marks is the object_id.

06:09 Make sure you save the code, restart the REPL, and give it a go.

06:15 So from serializer import Song, serialize and Book, then create your book or your song, my_book, and then serialize, not my_song, but my_book.

06:30 And do something that will work. XML. And there you go, that all still works fine. So there you have it. You have implemented the Factory Method design pattern using classes, using inheritance, using protocols, and using some other Pythonic tricks.

06:50 In the next lesson, you will reap the rewards of your hard work. What if the client suddenly also wants to have a playlist as part of their song object? So an ID, a title and an artist, but now also a playlist.

07:07 Now you will see that thanks to the flexibility that you have built into your code, adding a playlist to your song object is no problem at all.

Become a Member to join the conversation.