Fundamentals 11 min read

Unlock Python’s Power: 20 Essential Magic Methods Explained with Code

This article introduces twenty commonly used Python magic (dunder) methods, explains their purpose such as object initialization, representation, iteration, arithmetic, and context management, and provides clear code examples for each to help developers apply them in real‑world automation tasks.

Test Development Learning Exchange
Test Development Learning Exchange
Test Development Learning Exchange
Unlock Python’s Power: 20 Essential Magic Methods Explained with Code

Python provides a set of special "magic" methods—also called dunder methods because they begin and end with double underscores—that let developers customize object behavior for creation, representation, comparison, arithmetic, iteration, attribute access, and more. The following sections describe twenty of the most useful magic methods and include concrete code examples that can be directly used in automation scripts or other projects.

__init__(self[, args...])

Object initialization method called when a new instance is created.

class MyClass:
    def __init__(self, name):
        self.name = name

obj = MyClass("Alice")

__str__(self)

Returns a human‑readable string representation of the object.

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __str__(self):
        return f"({self.x}, {self.y})"

p = Point(3, 4)
print(p)  # Output: (3, 4)

__len__(self)

Defines the behavior of the built‑in len() function for the object.

class MyList:
    def __init__(self, items):
        self.items = items
    def __len__(self):
        return len(self.items)

my_list = MyList([1, 2, 3, 4, 5])
print(len(my_list))  # Output: 5

__getitem__(self, key)

Retrieves the element at the specified index or key.

class MyList:
    def __init__(self, items):
        self.items = items
    def __getitem__(self, index):
        return self.items[index]

my_list = MyList([1, 2, 3, 4, 5])
print(my_list[2])  # Output: 3

__setitem__(self, key, value)

Assigns a value to the element at the given index or key.

class MyList:
    def __init__(self, items):
        self.items = items
    def __setitem__(self, index, value):
        self.items[index] = value

my_list = MyList([1, 2, 3, 4, 5])
my_list[2] = 10
print(my_list.items)  # Output: [1, 2, 10, 4, 5]

__delitem__(self, key)

Deletes the element at the specified index or key.

class MyList:
    def __init__(self, items):
        self.items = items
    def __delitem__(self, index):
        del self.items[index]

my_list = MyList([1, 2, 3, 4, 5])
del my_list[2]
print(my_list.items)  # Output: [1, 2, 4, 5]

__contains__(self, item)

Implements the in operator to test membership.

class MyList:
    def __init__(self, items):
        self.items = items
    def __contains__(self, item):
        return item in self.items

my_list = MyList([1, 2, 3, 4, 5])
print(3 in my_list)  # Output: True

__iter__(self)

Returns an iterator object, enabling iteration with for loops.

class MyList:
    def __init__(self, items):
        self.items = items
    def __iter__(self):
        return iter(self.items)

my_list = MyList([1, 2, 3, 4, 5])
for item in my_list:
    print(item)  # Outputs: 1 2 3 4 5

__next__(self)

Provides the next element of an iterator; used when the object itself is an iterator.

class MyList:
    def __init__(self, items):
        self.items = items
        self.index = 0
    def __iter__(self):
        return self
    def __next__(self):
        if self.index >= len(self.items):
            raise StopIteration
        value = self.items[self.index]
        self.index += 1
        return value

my_list = MyList([1, 2, 3, 4, 5])
for item in my_list:
    print(item)  # Outputs: 1 2 3 4 5

__eq__(self, other)

Defines equality comparison between two objects.

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

p1 = Point(3, 4)
p2 = Point(3, 4)
print(p1 == p2)  # Output: True

__lt__(self, other)

Implements the less‑than (<) comparison.

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __lt__(self, other):
        return self.x < other.x and self.y < other.y

p1 = Point(2, 3)
p2 = Point(3, 4)
print(p1 < p2)  # Output: True

__gt__(self, other)

Implements the greater‑than (>) comparison.

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __gt__(self, other):
        return self.x > other.x and self.y > other.y

p1 = Point(3, 4)
p2 = Point(2, 3)
print(p1 > p2)  # Output: True

__add__(self, other)

Defines the behavior of the + operator for custom objects.

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)

v1 = Vector(1, 2)
v2 = Vector(3, 4)
result = v1 + v2
print(f"({result.x}, {result.y})")  # Output: (4, 6)

__sub__(self, other)

Defines the behavior of the subtraction ( -) operator.

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __sub__(self, other):
        return Vector(self.x - other.x, self.y - other.y)

v1 = Vector(3, 4)
v2 = Vector(1, 2)
result = v1 - v2
print(f"({result.x}, {result.y})")  # Output: (2, 2)

__mul__(self, other)

Defines multiplication behavior, often used for scaling.

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __mul__(self, factor):
        return Point(self.x * factor, self.y * factor)

p = Point(2, 3)
result = p * 2
print(f"({result.x}, {result.y})")  # Output: (4, 6)

__call__(self[, args...])

Makes an instance callable like a regular function.

class Calculator:
    def __call__(self, a, b):
        return a + b

calc = Calculator()
result = calc(3, 4)
print(result)  # Output: 7

__enter__(self) and __exit__(self, exc_type, exc_value, traceback)

Enable the object to be used as a context manager with the with statement.

class FileManager:
    def __init__(self, filename):
        self.filename = filename
    def __enter__(self):
        self.file = open(self.filename, 'r')
        return self.file
    def __exit__(self, exc_type, exc_value, traceback):
        self.file.close()

with FileManager("example.txt") as file:
    contents = file.read()
    print(contents)

__getattr__(self, name)

Called when attribute lookup fails, allowing custom handling of missing attributes.

class Person:
    def __getattr__(self, name):
        return f"Attribute '{name}' does not exist."

p = Person()
print(p.age)  # Output: Attribute 'age' does not exist.

__setattr__(self, name, value)

Intercepts attribute assignment, useful for validation or logging.

class Person:
    def __setattr__(self, name, value):
        print(f"Setting attribute '{name}' to '{value}'")
        super().__setattr__(name, value)

p = Person()
p.name = "Alice"  # Output: Setting attribute 'name' to 'Alice'

__delattr__(self, name)

Intercepts attribute deletion.

class Person:
    def __delattr__(self, name):
        print(f"Deleting attribute '{name}'")
        super().__delattr__(name)

p = Person()
# Assume p.name exists
p.name = "Bob"

del p.name  # Output: Deleting attribute 'name'

By mastering these magic methods, developers can write more expressive, Pythonic code and tailor object behavior to fit the needs of automation, APIs, and larger applications.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

PythonprogrammingTutorialObject-Orientedmagic methods
Test Development Learning Exchange
Written by

Test Development Learning Exchange

Test Development Learning Exchange

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.