__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@classmethod
Decorators - 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@classmethod
Decorators -
__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) -> 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__) # <class '__main__.MyMeta'> MyClass () {} # {'global_dict_name': 'global_dict', '__module__': '__main__', '__firstlineno__': 18, 'a': 1, 'b': 2, 'c': 3, '__static_attributes__': (), '__dict__': <attribute '__dict__' of 'MyClass' objects>, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, '__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!