A special method is a class method that Python calls in response to an operation on an instance. Its name begins and ends with double underscores, so special methods are also called “dunder” methods. Client code usually uses the operation rather than calling the method directly. section 17.5
For example, __str__ supplies a user-readable string when one is needed. Define it on a class, then print an instance: Python calls __str__ without an explicit call in your code. The __init__ method likewise runs when an instance is created. section 17.5 section 3.6
Listing 17.1 File color_module.py
class Color:
def __init__(self, red, green, blue):
self._red = red
self._green = green
self._blue = blue
def __str__(self):
return f"Color: R={self._red:d},G={self._green:d},B={self._blue:d}"
This small Color class defines __init__ to store three values and __str__ to format them for display. section 17.5
Printing an instance
After c = Color(15, 35, 3), print(c) displays a formatted Color string. The call is to print, not directly to c.__str__(). section 17.5
Other special methods let an object respond to familiar syntax:
- __getitem__ handles access such as obj[n]; __setitem__ handles assignment such as obj[n] = val. section 17.7.2
- __add__ lets an object respond to +, including a class’s version of list concatenation. section 17.7.2
A typed-list example checks element types on initialization and assignment, then stores and retrieves elements through __setitem__ and __getitem__. It permits expressions such as x[2] = "Hello" and x[2]. Those methods alone do not make a complete list replacement; further list behavior requires further special methods. section 17.8 section 17.7.2
class TypedList:
def __init__(self, example_element, initial_list=[]):
self.type = type(example_element)
if not isinstance(initial_list, list):
raise TypeError("Second argument of TypedList must "
"be a list.")
for element in initial_list:
self.__check(element)
self.elements = initial_list[:]
def __check(self, element):
if type(element) != self.type:
raise TypeError("Attempted to add an element of "
"incorrect type to a typed list.")
def __setitem__(self, i, element):
self.__check(element)
self.elements[i] = element
def __getitem__(self, i):
return self.elements[i]
The TypedList implementation shows type checking alongside the two methods that support indexed assignment and access. section 17.8
Add special methods when a class is meant to behave like a built-in type, but make the supported operations predictable. A file-backed line reader, for instance, may need to reject out-of-order indices rather than imply unrestricted list access. Even without broader built-in behavior, __str__ can make printed instances useful during debugging. Subclassing a built-in type is another option when the desired behavior is very close to it. section 17.10 section 17.7.2


