String Conversion in Python: When to Use __repr__ vs __str__

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hey everyone it's dan and it's time for another Python tricks video so today I want to talk about how you can control how a Python class is represented as a string and also when you interact with it or inspected in a Python interpreter session so let's start with a really simple example here so I've got my popular card class and we're just going to create a simple car object here and what you can see is that when I print this car object we kind of get this unsatisfying result and it's the same when I just inspect the object in this interpreter session so you can see here well at least it gives us the class name kind of the whole namespace of this thing but it you know only gives us the memory address if we run C Python you know just gives us this ID and it's it's kind of opaque and kind of hard to understand what's going on so this is better than nothing but it's not super useful and now there's a common workaround that I see some people apply for example they start printing out the class attributes directly and sure that works you know you can do that so we can kind of pry that class apart and kind of reach in and take out the the color and the the mileage here that works and then what I see some people do is they would kind of go ahead and do their own two string method right and then that would return or maybe like print directly or return return a string we're presenting the class but actually there is a convention inside Python that that handles all of that so you don't have to roll your own you don't have to come up with your own ways to do that because there's actually pre-existing conventions on how to do that so I want to explain to you how that works and basically what you're going to learn today is how the dunder stir and dunder wrapper methods work in Python this is gonna be a highly useful thing this is some a common interview question so you know watching this tutorial could literally pay you money in the future so you know stay tuned if you don't know how this stuff works okay so to kind of ease into this with a simple example I took the same car class and I added a dunder stir method here so the dunder methods or methods that start with a double underscore just kind of been shortened to dunder some people refer to them as magic methods a lot of people don't like that because they're not really supposed to be magical in any way they're just supposed to be while a Python convention and the kind of the dunder or the double underscore marks them as a core Python thing so kind of classes are not supposed to actually define their own dunder methods because they can could conflict with Python features in the future and so this is just a way I guess to kind of sum namespace these things a little bit or you know just by a naming convention kind of keeping them separate a little bit just like the dunder init method but you know total sidetrack here so what I've done here is I added a dunder stir method and basically what I did here whenever that method is called it just returns the color of the car and kind of tells us it's a car so you know just to show you an example here again I'm gonna create the same car and now when I print this car I actually get a completely different result right so this time I get a red car which is the result of this dunder stir method instead of this crazy string with the object address in memory however when I just inspect this object I still get the memory address and the previous result right so inspecting the car object still gives the same result but when I printed the car object I got this different result based on the stir method the the way you would actually convert an object to string if you if you wanted to force that or make that happen you would just use the built in stir method and then that is internally going to do the right thing and call the dunder stir method and it's gonna give you back the right result and now all of these functions that deal with text representations for objects like the print function they are going to do that internally right they're gonna do the they're gonna call the stir function for you and it would be the same with a format string for example so if you do this and this would also call stir and just give you the result but kind of the key thing is here that by convention if you add a stir method then it's gonna do a lot of good for you in controlling how your object is represented with or represented as a string so it's the pythonic way to do this which is kind of the holy grail right now still what you're seeing here was that when I inspected the my car object in the console I still got the same result so there seems to be different ways to convert your objects into strings and now the first one we just learned about it's called dunder stir and now the second one is called dunder wrapper and let's talk about what dunder repre does and how it's different to dunder stir in order to understand what's going on here I defined this class or you can kind of redefine my car class and what this new version of the car class does it actually has a repper and a stir implementation and now those implementations are just dummy implementations they're gonna tell us what's going on behind the scenes so if something calls wrapper behind the scenes we're gonna get rapper rapper for car as a result and if something calls stir wouldn't get stir for car as a result right so now we can kind of walk through the same example again and do a print my car you can see here okay called the stir function we could also go through the format example again you can see it called me stir function and now if we do my car and just inspect that we can see here that is actually called wrapper for the car and another way to to force this is to call the built-in wrapper function and then that's gonna do the right thing and call the the correct dunder repper implementation for this usually you just want to use the stir and wrapper helpers for that now of course the big question is okay so now we have these two what's what's actually the difference between them or what's a different use cases where where you would use them all right so we have stir and we have repper and they're both called by some convention but you know what's what's actually the difference like what shouldn't they return the same thing or how we're gonna deal with this and the answer that I've got for you is let's look at what some of the Python built in class or some of the classes from the Python standard library are doing here so what I'm gonna do here is I'm going to import the the date/time module and then we're just gonna create a new date object right so I just created a new date/time dot date object and then we're gonna try and experiment with that so we can see how it reacts right how does its stir and Ripper function react and what result do we get from it so let's call stir on that date object and you can see here we get a pretty concise representation it's quite readable looks like an ISO date format which is kind of standard representation for a date in string form and okay now we call wrapper on the same object instance it actually looks quite different because now we get a more elaborate result that is really unambiguous right so this is not any kind of date but we know exactly it's a date time dot date object and it was created in this way and we could even copy and paste this and execute that as valid Python it would recreate the same object right like I said earlier when you call like when you just inspect an object and an interpreter that also gives you the wrapper this gives us a pretty good idea of the difference between stir and repper so when you actually go to the Python documentation do some reading on the best practices that people have come up with in the community then you'll learn that the dunder stir method it's mainly used for giving an easy-to-read representation of your class right so stir should be easy to read and it's meant for human consumption right so you can see that here it says III so date you could just you know you could display that to a user and it wouldn't be too bad now with a wrapper on the other hand it should be unambiguous right so did I've typed that correctly yeah so with Reppert on the other hand it should be unambiguous so the goal here really is to be as explicit as possible about what this object is and it's I guess more meant for internal internal use and something that would make things easier to debug for a developer but you wouldn't necessarily want to display that to a user right and so some people actually recommend that the result of your repper should be something like this that that would actually be valid Python and that you could just run again it would recreate the same object now I find that personally I find that this is a really good idea but it's usually really hard to attain that in practice so I think the bottom line is that you want your repartee be unambiguous and more meant for developers but the stir you want that to be easy to read and potentially for human consumption so now another interesting or there are a couple more interesting things that I want to talk about here because they really you know they really make this whole thing a little bit easier to understand how it works in a real world so the next example I want to show you is an actual implementation that someone might take for for their class and because python falls back to calling wrapper if you don't define in a separate stir implementation my recommendation is actually put a dunder wrapper on any class that you define because then you get a pretty helpful and readable result in all cases and now what I'm gonna do is also give you a complete example of how you would do that because there there's some a slight trick you can apply to make this a little bit easier to work with so again we've got my car class here and I'm defining the wrapper and so how I would go about doing this is well returning a string that you know contains the car class name and then I probably do this color and self right and then that's a format string and in it which is past the self object now the common thing that I see here is that usually you have to retype the name of the class inside the wrapper but there's actually a way to get around that because we can just reach in to the class itself and ask it for its name so what you can do here instead is you can use self self dot class dot or dot dunder class dot dunder name this is getting kind of long so you want to make sure you format that in a way that's sensible but basically what this is going to do it's gonna automatically use the right name for the class so you don't have to make sure you update this right so you might not want that in some cases maybe you want the wrapper class name to be static but usually this is this is like a good default implementation for your reppers and now when I create a new my car object and I inspected I get a really nice result and also when I call stir on it or when I print the car I get the same result because the default implementation forrester just calls wrapper internally okay so this is kind of the minimum implementation I would recommend to you where you're adding a Reppert to any class that you define kind of leave the distr on the side and you would use something like this so you don't have to type the class name again okay so before we wrap this up there's one more thing I wanted to mention and that is how containers convert their child objects or the objects they contain to string and the maybe the surprising thing is that even if you call stir on a container so I'm creating this list object here even if you call stir on a container it's going to represent the internal objects with the reparation so when I you know I'm using the 2-day object which is just a date/time object or date/time dot date object so when I have this list here of these three date objects and then I call stir on it I actually get a string back that has the container and with the wrapper inside so this is just something to keep in mind how that works so if you wanted to kind of convert those with the stir function individually you just need a loop or some some kind of list comprehension to do that manually but you know that's just a side note I think really the bottom line or the one takeaway from this thing here is at least add a dunder wrapper to your classes all right so I hope you learned something new today and you're gonna be able to apply that in a real-world program or in some code that you write cool well happy Python Inc and I'll talk to you soon
Info
Channel: Real Python
Views: 77,469
Rating: undefined out of 5
Keywords: dbader, pytricks, python, python trick, __str__, __repr__, to string, string conversion, python programming, clean python, python tutorial, str vs repr, python class __str__ method, repr class, str__()__ and repr__()__ in python, difference between repr and str in python, python tutorials, python 3, special methods, magic methods, repr, python str, str, repr vs str, python repr, python dunders, python convert to string, python object to string, python to string, learn python, __
Id: aIdzBGzaxUo
Channel Id: undefined
Length: 14min 58sec (898 seconds)
Published: Tue Feb 07 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.