魔法方法python Python冷门魔术方法小结 魔法方法是什么

魔法方法python Python冷门魔术方法小结 魔法方法是什么

目录
  • __init_subclass__
  • __class_getitem__
  • __instancecheck__与__subclasscheck__
  • __prepare__
  • __mro_entries__

__init_subclass__

https://docs.python.org/3/reference/datamodel.htmlobject.__init_subclass__Python 3.6 新增。

父类派生子类后会调用该技巧,技巧中 cls 指向派生出的子类。

  • __init_subclass__被定义为普通技巧,将会被隐式转换为类技巧,故不必使用@classmethod装饰器
  • metaclass 不会被传给__init_subclass__
  • 传给一个新类的关键字参数会被传给父类的__init_subclass__。为保证与父类__init_subclass__兼容,应当将关键字参数中仅子类__init_subclass__需要的参数去掉后再传入父类__init_subclass__

class Base: def __init_subclass__(cls, /, name, kwargs): super().__init_subclass__(kwargs) print(“Base __init_subclass__ called”) cls.x = } cls.name = nameclass 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(A.x)print(A.name) 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__技巧的目的是允许标准库泛型类的运行时形参化以更方便地对这些类应用 类型提示。

  • __class_getitem__被定义为普通技巧,将会被隐式转换为类技巧,故不必使用@classmethod装饰器
  • __class_getitem__技巧应当返回一个 GenericAlias 类型

https://docs.python.org/3/reference/datamodel.htmlobject.__class_getitem__

from typing import Listclass 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__与__subclasscheck__

  • __instancecheck__可以自定义实例检查逻辑
  • __subclasscheck__可以自定义子类检查逻辑

from typing import Anyclass 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 Falseclass A(metaclass=Meta): passo = A()print(isinstance(123, A))print()print(issubclass(int, A)) Instance Check 123 True Subclass Check <class ‘int’> True

__prepare__

https://peps.python.org/pep-3115

Python 3.0 新增。

__prepare__用于为类准备命名空间。

  • __prepare__定义在元类中并且必须被显式定义为类技巧
  • __prepare__技巧返回一个映射对象
  • Python 执行类定义语句,会开头来说调用其元类__prepare__技巧,获得一个映射对象,该映射对象会被作为该类的命名空间,类的属性和技巧会被存储在该映射对象中,随后映射对象会成为该类的__dict__属性。

import collectionsfrom typing import Any, Mapping 创建一个 OrderedDict 对象作为字典global_dict = collections.OrderedDict()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_dictclass MyClass(metaclass=MyMeta): a = 1 b = 2 c = 3print(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__

https://docs.python.org/3/reference/datamodel.htmlobject.__mro_entries__

若某个类的父类不是type的实例(此时父类就一个普通对象),则定义该类时其基类会被替换为父类中定义的__mro_entries__技巧的返回值,若父类中没有定义__mro_entries__技巧,此时类的定义会报错AttributeError: &039;xxx&039; object has no attribute &039;mro&039;,由于无法进行MRO。

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(B1.mro())print(B2.mro()) <class ‘type’> True <class ‘__main__.A2’> True [<class ‘__main__.B1’>, <class ‘__main__.A1’>, <class ‘object’>] [<class ‘__main__.B2’>, <class ‘dict’>, <class ‘object’>]

到此这篇关于Python 冷门魔术技巧的文章就介绍到这了,更多相关Python 冷门魔术技巧内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

无论兄弟们可能感兴趣的文章:

  • 一文带你探索Python中15个常见的魔术技巧
  • 深入领会Python虚拟机中魔术技巧的使用
  • 深入领会Python虚拟机中常见魔术技巧的使用
  • Python魔术技巧深入分析讲解
  • python深入讲解魔术技巧
  • python进阶之魔术技巧详解
  • Python类型转换的魔术技巧详解
  • Python魔术技巧专题
  • Python魔术技巧详解