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

Converting to Product Classes

00:00 The first improvement you will make is to convert the product functions into product classes. Our product functions are on rows 34 and 38. To convert the first one into a class, let’s start by typing the words class, and then the name is _JSONSerializer.

00:23 The function, which is now on row 35, takes song as an input parameter. So you will want to create a class that takes song as an input parameter as well.

00:34 And you will want to instantiate the class. So we need an __init__() dunder method. Its first parameter is always .self, and then song as a second parameter.

00:46 And all this __init__() method will do is assign the song input parameter to the instance attribute .self.song.

00:56 What will you do with the _serialize_to_json() function? Well, first of all, let’s convert that into a method by making it part of the class.

01:05 So select both rows, press Tab, and now the def is within the class. The second thing to do is to then pass in self instead of song, because this is now a method, but then thinking about what we’re trying to achieve.

01:20 We are trying to get a string representation of the JSONSerializer class or of the instance of that class. And that is actually exactly what the __str__() dunder method is for.

01:32 So if you rename that to __str__(),

01:38 then that is the __str__() dunder method. What is left to do for the _JSONSerializer class is to change song. As you can see in row 38, change that to self.song because the self object is passed into the __str__() method.

01:55 So self.song. Now I’m just going to put this on a separate line:

02:03 self.song for the title, and the artist is self.song.artist. So just to summarize what is happening, self is passed into the __str__() dunder method, and self represents an instance of the _JSONSerializer class.

02:23 And that instance contains the song object as the self.song instance attribute. Why is that? Because in row 35, the song object is assigned to the self.song class attribute.

02:38 Therefore in rows 38, 39 and 40, self.song is a song object, which means you have access to song.id and .artist.

02:51 So that’s how the JSONSerializer class works. The next step, of course, is to do the same thing or something very similar for the _serialize_to_xml() product function on row 43.

03:05 So if you type class, of course call that _XMLSerializer,

03:12 you will need an __init__() method again. So __init__() self is a first parameter, song is the second one, just as before.

03:24 And now there are a few more instance attributes to create. In fact, if you just scroll down a little bit, all these, so lines 46 to 50, you will want to convert to instance attributes.

03:39 So the fastest way to do that that I can think of is to delete the def, use Tab, and type self in front of these variable names to convert them to attributes.

03:53 Of course, when you do that, you need to be careful. song_info is no longer a known variable name, but self.song_info is because that is what you created on row 44.

04:10 Change that to self.song_info, and the same thing on row 47. What’s left to do is to create the __str__() dunder method.

04:24 Again, taking self as an input parameter, bring the return statement there into the def, and then song_info is no longer recognized.

04:35 That becomes self.song_info. Just for good measure, please add an extra row here. So there you have it. Those are your two product classes. Now there are two things left to do.

04:49 One, please scroll back up to the Creator. The creator function refers to the _serialize_to_json() and _serialize_to_xml() functions on rows 23 and 25.

05:02 Of course, they no longer exist. We’ve replaced them with classes. So we are going to reference the classes here. So I’m just going to copy-paste.

05:15 And then there is the _XMLSerializer, which I copy from row 42, and then copy that into row 25. So it’s important to understand now that the _get_serializer() creator returns classes, it does not return instances of classes, it returns classes.

05:35 So how do we get instances of classes? Well, we moved instantiation or execution of functions in the previous step out of the creator and into the serialize() function.

05:47 So if you move up to the serialize() function, you will make the second change here. So you now know that the creator function _get_ serializer() returns a class object.

06:00 So that class object is captured in serializer _product in line 13. So in line 14, an instance is then created of that class object by passing song into it, and then that is returned to the client.

06:17 So you are returning to the client the instance of a product class. Now that is not entirely what the client asks for. The client asks for a string. So how do you create a string representation of a class instance?

06:33 Ha. Well, that is exactly what the __str__() dunder method allows you to do. So the __str__() method that you have just implemented in your class allows you to pass a class instance into the str() function.

06:52 So on line 14, where you return the class instance, you are now going to return a string representation. So you’re going to pass that class instance into the str() function, just like that.

07:06 So by typing str(, open parentheses and then the class instance, and then close parentheses. So now that should meet the brief for the client, and all that’s left to do is to see how the code works.

07:20 So if you please save your code and then restart your REPL, and then type the following: from serializer

07:32 import Song and serialize,

07:36 and create a Song

07:42 which needs an ID, title, and artist,

07:48 and then serialize(), pass in the song. So my_song and choose a format, let’s start with XML, and indeed I get the string representation.

08:03 And let’s pick JSON. There you go, as expected. And then let’s pick something we haven’t implemented yet. And indeed the ValueError is being raised.

08:19 So that works. Wow, okay. That was quite a lesson. You have managed to do a lot of refactoring under the hood, and that makes your code far more robust. And you have also achieved to not change the interface.

08:35 What was happening in the REPL is exactly the same. So from the point of view of the client, your tinkering and code improvements have not changed the client experience.

08:46 So that is great work, well done. In the next lesson, you’ll make the code just a little bit more Pythonic by looking at data classes.

Become a Member to join the conversation.