Decoding Python Magic -> __str__ , __repr__ and __format__
Let’s master object representation.
Greetings Everyone,
Today, in the next installment of the “Decoding Python Magic” series, we will delve into the magic methods __str__
, __repr__
, and __format__
. If you haven't already, feel free to check out our previous discussions on important magic methods, including the Descriptor Protocol, for a comprehensive understanding of Python's powerful capabilities.
__str__
and __repr__
are indeed commonly used magic methods in Python, with __format__
being less commonly known but equally important.
__str__
The __str__
method is a special method in Python that defines how an object should be represented as a string when using the str()
function or when the object is used in string formatting with the f-string
syntax.
It’s meant to provide a readable, user-friendly representation of the object.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"{self.name} - {self.age}"
p = Person("Alice", 30)
print(p) # Alice - 30
print(f'Person: {p}') # Person: Alice - 30
How to see SQL query prepared by Django ORM ?
In [5]: authors = Author.objects.filter(name="Test Author")
In [6]: print(authors.query)
SELECT "core_author"."id", "core_author"."name", "core_author"."last_name" FROM "core_author" WHERE "core_author"."name" = Test Author
__str__
method of query
returns SQL query.
__repr__
The __repr__
method is another special method which gives string representation of the object. Unlike __str__
, which is meant to be readable by humans, __repr__
should return a string that represents a valid Python expression that could be used to recreate the object. It's used by the repr()
function and the interactive interpreter.
__repr__
means to be read by other developers.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point({self.x}, {self.y})"
point = Point(3, 4)
print(repr(point)) # Output: "Point(3, 4)"
__repr__ can be called by repr function.
repr use cases
- Serialization: When serializing objects (e.g., to JSON or XML),
__repr__
can be used to provide a string representation that can be easily converted back into an object. This is particularly useful in web development and data processing applications. - Interactive Console: When working in an interactive Python console (e.g., in an IDE or Jupyter notebook),
__repr__
is used to display the result of an expression or variable. Having a meaningful__repr__
implementation makes it easier to understand the content and structure of objects. - Logging and Debugging.
In [1]: class Point:
2 def __init__(self, x, y):
3 self.x = x
4 self.y = y
5
6 def __repr__(self):
7 return f"Point({self.x}, {self.y})"
In [2]: p = Point(10, 20)
In [3]: p
Out[3]: Point(10, 20)
In [4]: repr(p)
Out[4]: 'Point(10, 20)'
In [5]: str(p)
Out[5]: 'Point(10, 20)'
__str__ can take __repr__ representation if only __repr__ is defined.
In [9]: class Person:
2 def __init__(self, name, age):
3 self.name = name
4 self.age = age
5
6 def __str__(self):
7 return f"{self.name} - {self.age}"
8
9 p = Person("Alice", 30)
10 print(p)
11 p
Alice - 30
Out[9]: <__main__.Person at 0x771909117a00>
__repr__ will have specific representation only if overridden otherwise it will call base class __repr__.
__format__
The __format__
method allows an object to customize its behavior when used with the format()
function or with string formatting using the format()
method or f-strings. It takes two arguments: format_spec
(the formatting specification) and returns the formatted string.
Let’s create date formatter.
import datetime
class Date:
def __init__(self, year, month, day):
self.date = datetime.datetime(year, month, day)
def __format__(self, format_spec):
if not format_spec:
format_spec = "%D"
return self.date.strftime(format_spec)
date = Date(2024, 4, 15)
print(format(date)) # 04/15/24
print(format(date, "%d/%m/%Y")) # 15/04/2024
print(format(date, "%B %Y")) # April 2024
print(f"{date:%B %Y}") # April 2024
You can refer this PEP to learn more.
Conclusion
Object representation is an essential aspect for understanding an object’s behavior on the fly. The methods we discussed today, such as __str__
, __repr__
, and __format__
, are general-purpose and widely used.
Our goal should be to design objects in a way that helps other developers maintain them in the long run. I sometimes refer to these methods as "metadata methods" because they provide additional details about the object itself.
Hope you find it helpful. Follow Rahul Beniwal for more articles.
Other similar articles by me.