SoFunction
Updated on 2025-04-16

Python’s unpopular magic method summary

__init_subclass__

/3/reference/#object.__init_subclass__Python 3.6 has been added.

The parent class will call the method after derives a child class, and cls points to the derived child class.

  • like__init_subclass__Defined as a normal method, it will be implicitly converted to a class method, so it does not need to be used@classmethodDecorators
  • metaclass will not be passed to__init_subclass__
  • The keyword argument passed to a new class will be passed to the parent class__init_subclass__. To ensure that with parent class__init_subclass__Compatible, only subclasses should be placed in keyword parameters__init_subclass__Remove the required parameters and then pass them into the parent class__init_subclass__
class Base:
    def __init_subclass__(cls, /, name, **kwargs):
        super().__init_subclass__(**kwargs)
        print("Base __init_subclass__ called")
         = {}
         = name


class A(Base, name="Jack"):
    def __init__(self):
        super().__init__()
        print("A __init__ called")

    def __new__(cls, *args, **kwargs):
        super().__new__(cls)
        print("A __new__ called")


print()
print()
# Base __init_subclass__ called
# {}
# Jack
class A:
    def __init__(self):
        super().__init__()
        print("A __init__ called")

    def __new__(cls, *args, **kwargs):
        super().__new__(cls)
        print("A __new__ called")

    @classmethod
    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__()
        print(kwargs)
        print("A __init_subclass__ called")


class B(A, bbb=12):
    def __init__(self):
        super().__init__()
        print("B __init__ called")

    def __new__(cls, *args, **kwargs):
        super().__new__(cls)
        print("B __new__ called")

    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__()
        print("B __init_subclass__ called")


class C(B, ccc=12):
    def __init__(self):
        super().__init__()
        print("C __init__ called")

    def __new__(cls, *args, **kwargs):
        super().__new__(cls)
        print("C __new__ called")

    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__()
        print("C __init_subclass__ called")

__class_getitem__

__class_getitem__The purpose of the method is to allow runtime parameterization of standard library generic classes to more conveniently apply type prompts to these classes.

  • like__class_getitem__Defined as a normal method, it will be implicitly converted to a class method, so it does not need to be used@classmethodDecorators
  • __class_getitem__The method should return a GenericAlias ​​type

/3/reference/#object.__class_getitem__

from typing import List


class A:

    def __class_getitem__(cls, item):
        print(item)
        return "abc"


print(A[0])

if __name__ == '__main__':
    int_arr_type = List[int]
    list1: int_arr_type = [1]
    list2: int_arr_type = []
    print(int_arr_type)

__instancecheck__ and __subclasscheck__

  • __instancecheck__Can customize instance check logic
  • __subclasscheck__Subclass check logic can be customized
from typing import Any

class Meta(type):
    def __instancecheck__(self, instance: Any) -> bool:
        print("Instance Check")
        print(instance)
        return True

    def __subclasscheck__(self, subclass: type) -> bool:
        print("Subclass Check")
        print(subclass)
        if subclass is int:
            return True
        return False


class A(metaclass=Meta):
    pass


o = A()

print(isinstance(123, A))

print()

print(issubclass(int, A))

# Instance Check
# 123
# True
# 
# Subclass Check
# <class 'int'>
# True

__prepare__

/pep-3115

Python 3.0 has been added.

__prepare__Used to prepare namespaces for classes.

  • __prepare__Defined in a metaclass and must be explicitly defined as a class method
  • __prepare__Method returns a mapped object
  • Python executes a class definition statement and will first call its metaclass__prepare__Method, obtain a mapping object, the mapping object will be used as the namespace of the class, the attributes and methods of the class will be stored in the mapping object, and the mapping object will then become the__dict__property.
import collections
from typing import Any, Mapping

# Create an OrderedDict object as a dictionaryglobal_dict = ()

global_dict["global_dict_name"] = "global_dict"


class MyMeta(type):

    @classmethod
    def __prepare__(metacls, __name: str, __bases: tuple[type, ...], **kwargs: Any) -&gt; Mapping[str, object]:
        print(metacls, __name, __bases, kwargs)
        return global_dict


class MyClass(metaclass=MyMeta):
    a = 1
    b = 2
    c = 3


print(MyClass.__dict__)
print("global_dict_name" in MyClass.__dict__)

# &lt;class '__main__.MyMeta'&gt; MyClass () {}
# {'global_dict_name': 'global_dict', '__module__': '__main__', '__firstlineno__': 18, 'a': 1, 'b': 2, 'c': 3, '__static_attributes__': (), '__dict__': &lt;attribute '__dict__' of 'MyClass' objects&gt;, '__weakref__': &lt;attribute '__weakref__' of 'MyClass' objects&gt;, '__doc__': None}
# True

__mro_entries__

/3/reference/#object.__mro_entries__

If the parent class of a certain class is not an instance of type (the parent class is a normal object at this time), then when defining the class, its base class will be replaced with the one defined in the parent class.__mro_entries__The return value of the method, if there is no definition in the parent class__mro_entries__Method, the definition of the class will report an error at this timeAttributeError: 'xxx' object has no attribute 'mro', because MRO cannot be performed.

class A1:
    ...

class A2:
    def __mro_entries__(self, bases):
        return (dict,)

class B1(A1):
    print(type(A1), type(A1) is type)
    ...

class B2(A2()):
    print(type(A2()), type(A2()) is not type)
    ...

print(())
print(())
# <class 'type'> True
# <class '__main__.A2'> True
# [<class '__main__.B1'>, <class '__main__.A1'>, <class 'object'>]
# [<class '__main__.B2'>, <class 'dict'>, <class 'object'>]

This is the end of this article about the summary of Python’s unpopular magic methods. For more related contents of Python’s unpopular magic methods, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!