SoFunction
Updated on 2025-03-04

Examples of magic functions and magic attribute usage in Python

Preface

Magic functions in Python, also known as special methods or double underscore methods, are some specially named functions in Python that start and end with double underscores. These functions define the behavior of an object in a specific situation, such as creation, comparison, operation, iteration, etc.

Magic functions are mainly designed for certain special needs. For example, the __str__() and __repr__() functions are used to print out the information of the output object, the __add__() function is used to define the behavior of adding two objects, and the __len__() function defines the behavior when called by len(), etc. Python magic functions are a way to implement Python syntax sugar, improving the readability and maintainability of the code. For example, when objects are added, people are more accustomed to the form of c = a + b. If the user can automatically call a.__add__(b) using a + b, it will naturally be much more convenient, and magic functions happen to have this function.

Magical functions

__init__

__init__ object initialization function is automatically called when instantiating objects. I won't say much about this most familiar one.

class TestClass:
    def __init__(self, name):
         = name

obj = TestClass("Alice")

__str__

Returns the string representation of an object in a user-friendly manner, called automatically when str() is used.

class PointClass:
    def __init__(self, x, y):
         = x
         = y

    def __str__(self):
        return f"({}, {})"

p = PointClass(3, 4)
print(p)  # (3, 4)

__repr__

Returns the string representation of the object in a developer-friendly manner, and is automatically called when using repr(). When printing an object using the print() function, the first thing that is called is the __str__ method. If the object does not define the __str__ method, the __repr__ method will be called.

class PointClass:
    def __init__(self, x, y):
         = x
         = y

    def __str__(self):
        return f"({}, {})"

    def __repr__(self):
        return f"Point({}, {})"

p = PointClass(3, 4)
print(p)  # (3, 4)
print(str(p))  # (3, 4)
print(repr(p))  # Point(3, 4)

__len__

Returns the length of the object, called automatically using len().

class ListClass:
    def __init__(self, items):
         = items

    def __len__(self):
        return len()

my_list = ListClass([1, 2, 3, 4, 5])
print(len(my_list))  # 5

__missing__

When trying to access a key that does not exist in the dictionary, if__missing__method, it will be called, not thrownKeyError

class DictClass(dict):

    def __missing__(self, key):
        self[key] = "default"
        return "default"

my_dict = DictClass({'a': 1, 'b': 2})
print(my_dict['c'])  # default
print(my_dict.keys())  # dict_keys(['a', 'b', 'c'])

my_dict = dict({'a': 1, 'b': 2})
print(my_dict['c'])  # KeyError: 'c'

__getitem__

Gets the specified element of the object when using the index operator[]Called automatically when accessing elements of an object.

class DictClass:
    def __init__(self, items):
         = items

    def __getitem__(self, key):
        return (key)

my_dict = DictClass({'a': 1, 'b': 2})
print(my_dict['a'])  # 1

__setitem__

Sets the value to the specified element of the object, and is automatically called when setting the value to the object.

class DictClass:
    def __init__(self, items):
         = items

    def __setitem__(self, key, value):
        [key] = value

my_dict = DictClass({'a': 1, 'b': 2})
my_dict['c'] = 3
print(my_dict.items)  # {'a': 1, 'b': 2, 'c': 3}

__delitem__

Delete the object specified element and is automatically called when deleting the object element using del.

class DictClass:
    def __init__(self, items):
         = items

    def __delitem__(self, key):
        del [key]

my_dict = DictClass({'a': 1, 'b': 2})
del my_dict['a']
print(my_dict.items)  # {'b': 2}

__contains__

Determines whether the object contains a specified element and is automatically called when using in to judge.

class ListClass:
    def __init__(self, items):
         = items

    def __contains__(self, item):
        return item in 

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

__iter__

Returns the iterator object.

class ListClass:
    def __init__(self, items):
         = items

    def __iter__(self):
        return iter()

my_list = ListClass([1, 2, 3, 4, 5])
for item in my_list:
    print(item)  # Output in sequence: 1, 2, 3, 4, 5

__next__

Returns the next element of the iterator, which is automatically called when looping through the object elements.

class ListClass:
    def __init__(self, items):
         = items
         = 0

    def __iter__(self):
        return self

    def __next__(self):
        if  >= len():
            raise StopIteration
        value = []
         += 1
        return value

my_list = ListClass([1, 2, 3, 4, 5])
for item in my_list:
    print(item)  # Output in sequence: 1, 2, 3, 4, 5

__eq__

Determine whether the two objects are equal, and are automatically called when the two objects are judged using ==.

class PointClass:
    def __init__(self, x, y):
         = x
         = y

    def __eq__(self, other):
        return  ==  and  == 

p1 = PointClass(3, 4)
p2 = PointClass(3, 4)
p3 = PointClass(5, 6)
print(p1 == p2)  # True
print(p1 == p3)  # False

__abs__

Output the absolute value of the object.

class PointClass:
    def __init__(self, x, y):
         = x
         = y

    def __abs__(self):
        return ( *  +  * ) ** 0.5

p1 = PointClass(3, 4)
print(abs(p1))  # 5.0

__lt__

Determine whether an object is smaller than another object.

class PointClass:
    def __init__(self, x, y):
         = x
         = y

    def __lt__(self, other):
        return  <  and  < 

p1 = PointClass(3, 4)
p2 = PointClass(3, 4)
p3 = PointClass(5, 6)
print(p1 < p2)  # False
print(p1 < p3)  # True

 __le__

Determines whether an object is smaller than or equal to another object.

class PointClass:
    def __init__(self, x, y):
         = x
         = y

    def __le__(self, other):
        return  <=  and  <= 

p1 = PointClass(3, 4)
p2 = PointClass(3, 4)
p3 = PointClass(5, 6)
print(p1 <= p2)  # True
print(p1 <= p3)  # True

 __gt__

Determine whether an object is larger than another object.

class PointClass:
    def __init__(self, x, y):
         = x
         = y

    def __gt__(self, other):
        return  >  and  > 

p1 = PointClass(3, 4)
p2 = PointClass(3, 4)
p3 = PointClass(1, 2)
print(p1 > p2)  # False
print(p1 > p3)  # True

 __ge__

Determines whether an object is greater than or equal to another object.

class PointClass:
    def __init__(self, x, y):
         = x
         = y

    def __ge__(self, other):
        return  >=  and  >= 

p1 = PointClass(3, 4)
p2 = PointClass(3, 4)
p3 = PointClass(1, 2)
print(p1 >= p2)  # True
print(p1 >= p3)  # True

 __add__

Defines the addition operation of the object, and is automatically called between objects using +.

class PointClass:
    def __init__(self, x, y):
         = x
         = y

    def __add__(self, other):
        return PointClass( + ,  + )

    def __str__(self):
        return f"({}, {})"

p1 = PointClass(1, 2)
p2 = PointClass(3, 4)
print(p1 + p2)  # (4, 6)

 __sub__

Define the subtraction operation of objects, and use - automatically called between objects.

class PointClass:
    def __init__(self, x, y):
         = x
         = y

    def __sub__(self, other):
        return PointClass( - ,  - )

    def __str__(self):
        return f"({}, {})"

p1 = PointClass(1, 2)
p2 = PointClass(3, 4)
print(p1 - p2)  # (-2, -2)

 __mul__

Define the multiplication operation of objects, and use * to automatically call between objects. Object multiplication and number multiplication can be performed according to the operand type.

class PointClass:
    def __init__(self, x, y):
         = x
         = y

    def __mul__(self, other):
        if isinstance(other, PointClass):
            return PointClass( * ,  * )
        elif isinstance(other, int) or isinstance(other, float):
            return PointClass( * other,  * other)
        else:
            raise TypeError(f"Unsupported operand type: {type(other)}")

    def __str__(self):
        return f"({}, {})"

p1 = PointClass(1, 2)
p2 = PointClass(3, 4)
print(p1 * p2)  # (3, 8)
print(p1 * 3)  # (3, 6)
print(p1 * "t")  # TypeError: Unsupported operand type: <class 'str'>

__call__

Makes the object callable.

class Calculator:

    def __init__(self, x, y):
         = x
         = y

    def __call__(self):
        return  + 

calc = Calculator(3, 4)
result = calc()
print(result)  # 7
class Calculator:
    def __call__(self, a, b):
        return a + b

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

__getattr__

Called when accessing properties that do not exist in the object.

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

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

__setattr__

Called automatically when setting class instance properties.

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

p = Person()
 = "Alice"  # Setting attribute 'name' to 'Alice'
print()  # Alice

__delattr__

Called automatically when object properties are deleted.

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

p = Person()
 = "Alice"
print()  # Alice
del   # Deleting attribute 'name'
print()  # AttributeError: 'Person' object has no attribute 'name

__enter__

The __enter__() method is used to perform operations before entering a code block defined by the context manager.

__exit__

The __exit__() method of the context manager also has three parameters, namely the exception type, the outlier value and the trace information. If an exception occurs in the with statement block, these parameters are passed to the __exit__() method, where relevant processing can be performed.

__del__

Python's garbage collection mechanism calls this method when the object is no longer referenced.

class FileHandler:
    def __init__(self, filename):
         = filename

    def __enter__(self):
        print("goto __enter__ open file")
         = open(, 'w', encoding='utf-8')
        return 

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("goto __exit__ close file")
        ()

    def __del__(self):
        print("goto __del__ release resource")

print("process start")
with FileHandler("./") as f:
    ("hello world!\n")
print("process end")
# process start
# goto __enter__ open file
# goto __exit__ close file
# goto __del__ release resource
# process end

Magical attributes

__dict__

__dict__ Included by__init__The attributes and values ​​of the method initialization.

class TestClass:
    def __init__(self, name):
         = name

    def test(self):
         = 25

obj = TestClass("Alice")
print(obj.__dict__)  # {'name': 'Alice'}
# print(TestClass.__dict__)

__slots__

Built-in class properties__slots__is a special built-in class attribute that can be used to define a collection of attribute names of a class. Once defined in the class__slots__Properties, Python will restrict instances of this class to only have__slots__attributes defined in .

class Person:
    __slots__ = ('name', 'age')

    def __init__(self, name, age):
         = name
         = age
         = ""  # AttributeError: 'Person' object has no attribute 'address'

person = Person("Alice", 30)
print()  # Output "Alice"print()  # Output 30print(person.__slots__)  # ('name', 'age')

Summarize

This is the article about magic functions and magic properties in Python. For more related contents of magic functions and magic properties in Python, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!