Python 冷門(mén)魔術(shù)方法小結(jié)
__init_subclass__
https://docs.python.org/3/reference/datamodel.html#object.__init_subclass__Python 3.6 新增。
父類派生子類后會(huì)調(diào)用該方法,方法中 cls 指向派生出的子類。
- 若
__init_subclass__
被定義為普通方法,將會(huì)被隱式轉(zhuǎn)換為類方法,故不必使用@classmethod
裝飾器 - metaclass 不會(huì)被傳給
__init_subclass__
- 傳給一個(gè)新類的關(guān)鍵字參數(shù)會(huì)被傳給父類的
__init_subclass__
。為保證與父類__init_subclass__
兼容,應(yīng)當(dāng)將關(guān)鍵字參數(shù)中僅子類__init_subclass__
需要的參數(shù)去掉后再傳入父類__init_subclass__
class Base: def __init_subclass__(cls, /, name, **kwargs): super().__init_subclass__(**kwargs) print("Base __init_subclass__ called") cls.x = {} cls.name = 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(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__
方法的目的是允許標(biāo)準(zhǔn)庫(kù)泛型類的運(yùn)行時(shí)形參化以更方便地對(duì)這些類應(yīng)用 類型提示。
- 若
__class_getitem__
被定義為普通方法,將會(huì)被隱式轉(zhuǎn)換為類方法,故不必使用@classmethod
裝飾器 __class_getitem__
方法應(yīng)當(dāng)返回一個(gè) GenericAlias 類型
https://docs.python.org/3/reference/datamodel.html#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__與__subclasscheck__
__instancecheck__
可以自定義實(shí)例檢查邏輯__subclasscheck__
可以自定義子類檢查邏輯
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__
https://peps.python.org/pep-3115
Python 3.0 新增。
__prepare__
用于為類準(zhǔn)備命名空間。
__prepare__
定義在元類中并且必須被顯式定義為類方法__prepare__
方法返回一個(gè)映射對(duì)象- Python 執(zhí)行類定義語(yǔ)句,會(huì)首先調(diào)用其元類
__prepare__
方法,獲得一個(gè)映射對(duì)象,該映射對(duì)象會(huì)被作為該類的命名空間,類的屬性和方法會(huì)被存儲(chǔ)在該映射對(duì)象中,隨后映射對(duì)象會(huì)成為該類的__dict__
屬性。
import collections from typing import Any, Mapping # 創(chuàng)建一個(gè) OrderedDict 對(duì)象作為字典 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_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__
https://docs.python.org/3/reference/datamodel.html#object.__mro_entries__
若某個(gè)類的父類不是type的實(shí)例(此時(shí)父類就是一個(gè)普通對(duì)象),則定義該類時(shí)其基類會(huì)被替換為父類中定義的__mro_entries__
方法的返回值,若父類中沒(méi)有定義__mro_entries__
方法,此時(shí)類的定義會(huì)報(bào)錯(cuò)AttributeError: 'xxx' object has no attribute 'mro'
,因?yàn)闊o(wú)法進(jìn)行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'>]
到此這篇關(guān)于Python 冷門(mén)魔術(shù)方法小結(jié)的文章就介紹到這了,更多相關(guān)Python 冷門(mén)魔術(shù)方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python基于opencv檢測(cè)程序運(yùn)行效率
這篇文章主要介紹了python基于opencv檢測(cè)程序運(yùn)行效率,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12python解決12306登錄驗(yàn)證碼的實(shí)現(xiàn)
這篇文章主要介紹了python解決12306登錄驗(yàn)證碼的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04python智聯(lián)招聘爬蟲(chóng)并導(dǎo)入到excel代碼實(shí)例
這篇文章主要介紹了python智聯(lián)招聘爬蟲(chóng)并導(dǎo)入到excel代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5時(shí)間控件QTimer詳細(xì)使用方法與實(shí)例
這篇文章主要介紹了python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5時(shí)間控件QTimer詳細(xì)使用方法與實(shí)例,需要的朋友可以參考下2020-02-02python正則表達(dá)式完成車牌號(hào)檢驗(yàn)的代碼實(shí)例
這篇文章主要給大家介紹了關(guān)于python正則表達(dá)式完成車牌號(hào)檢驗(yàn)的相關(guān)資料,在Python中正則表達(dá)式是一種用于匹配和操作字符串的強(qiáng)大工具,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-02-02AI生成圖片Stable?Diffusion環(huán)境搭建與運(yùn)行方法
Stable?Diffusion是一種基于擴(kuò)散過(guò)程的生成模型,由Ge?et?al.在2021年提出,該模型利用了隨機(jī)變量的穩(wěn)定分布,通過(guò)遞歸地應(yīng)用擴(kuò)散過(guò)程來(lái)生成高質(zhì)量的圖像,這篇文章主要介紹了AI圖片生成Stable?Diffusion環(huán)境搭建與運(yùn)行,需要的朋友可以參考下2023-05-05