>>> format(sys.stdout)
"<_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>"
>>> str(sys.stdout)
"<_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>"
I am not very sure about the following quotes from Python library references. What differences are between format()
and str()
, or between object.__format__(self, format_spec)
and object.__str__(self )
? When shall we use which?
object.__str__(self )
Called by str(object) and the built-in functions format() and print() to compute the “informal” or nicely printable string representation of an object.
object.__format__(self, format_spec)
Called by the format() built-in function, and by extension, evaluation of formatted string literals and the str.format() method, to produce a “formatted” string representation of an object.
I am gonna break down the main three (technically main 2 because __format__
is not commonly implemented). I'll go through all three then put it all together in one nice class.
The most common __str__
:
This is how you want to represent this object as a str
.
Often this is less detailed than __repr__
and is used
mainly for the end user. For example if we have a person
class we may implement str
this way:
class Person:
def __init__(self, name):
self.name = name
def __str__(self):
return f"Hello my name is {self.name}"
p = Person("John Smith")
print(str(p)) # Prints "Hello my name is John Smith"
The less common __repr__
:
To be honest I implement this more than str
for most projects. This should return the representation of the object as a str
in such a way that it is helpful to the developer instead of the end user and is called via repr(my_obj)
. If a class does not implement a __str__
magic method then python will attempt to call its __repr__
method automatically when you use str(my_obj)
(thus you can implement repr
first and str
later). Often the repr
of a class returns the way to recreate that object. For example:
class Person:
def __init__(self, name):
self.name = name
def __repr__(self):
return f"Person(name='{self.name}')"
p = Person("John Smith")
print(repr(p)) # Prints "Person(name='John Smith')"
print(str(p)) # Prints "Person(name='John Smith')"
The cursed child __format__
: [I just call it that because it is so uncommonly used :)]
The main difference between __format__
and the other two methods is that it also accepts a format_spec
that can be used to style the returned string.
To understand this in further detail I must first explain some formatting stuff. You may have seen some of this stuff before or you may not have.
Lets use a dummy class:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f'Person(name="{self.name}", age={self.age})'
def __str__(self):
return str(self.name)
p = Person(name="John Smith", age=22)
# This prints the str of p
print("{!s}".format(p)) # John Smith
# This prints the representation of p
print("{!r}".format(p)) # Person(name="John Smith", age=22)
Okay so you can format your class as its str
or as its repr
, but what if you want to format it your own way? Most people don't need to do this; but, this is the power of python, you can do anything. We can create different tags instead of r
and s
(though it uses :
instead of !
):
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f'Person(name="{self.name}", age={self.age})'
def __str__(self):
return str(self.name)
def __format__(self, format_spec):
if format_spec == 'age': # get a persons age
return f"{self.name} is {self.age} years old"
elif format_spec == 'birthday':
return "Yesterday"
return str(self) # A default case
p = Person(name="John Smith", age=22)
# This prints the str of p
print("{!s}".format(p))
# This with representation of p
print("{!r}".format(p))
print("{:age}".format(p))
print("{:birthday}".format(p))
print(f"{p:age} and his birthday was {p:birthday}")
There is obviously more to this than my limited knowledge can go into but this should be a good general scope :).
There are some packages that use this such as datetime
. If you are interested learning more about the power of format Pyformat walks through this pretty well: PyFormat.
I do not have much experience using __format__
so I can not provide a good use-case (though datetime's use-case isn't bad). Everything here is just to show the broad difference between str
, repr
, and format
magic methods. If I got anything wrong (especially __format__
's use-case) please let me know and I will update it.