Python 冷門魔術(shù)方法小結(jié)
__init_subclass__
https://docs.python.org/3/reference/datamodel.html#object.__init_subclass__Python 3.6 新增。
父類派生子類后會調(diào)用該方法,方法中 cls 指向派生出的子類。
- 若
__init_subclass__被定義為普通方法,將會被隱式轉(zhuǎn)換為類方法,故不必使用@classmethod裝飾器 - metaclass 不會被傳給
__init_subclass__ - 傳給一個新類的關(guān)鍵字參數(shù)會被傳給父類的
__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)庫泛型類的運行時形參化以更方便地對這些類應(yīng)用 類型提示。
- 若
__class_getitem__被定義為普通方法,將會被隱式轉(zhuǎn)換為類方法,故不必使用@classmethod裝飾器 __class_getitem__方法應(yīng)當(dāng)返回一個 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__可以自定義實例檢查邏輯__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__方法返回一個映射對象- Python 執(zhí)行類定義語句,會首先調(diào)用其元類
__prepare__方法,獲得一個映射對象,該映射對象會被作為該類的命名空間,類的屬性和方法會被存儲在該映射對象中,隨后映射對象會成為該類的__dict__屬性。
import collections
from typing import Any, Mapping
# 創(chuàng)建一個 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_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__
若某個類的父類不是type的實例(此時父類就是一個普通對象),則定義該類時其基類會被替換為父類中定義的__mro_entries__方法的返回值,若父類中沒有定義__mro_entries__方法,此時類的定義會報錯AttributeError: 'xxx' object has no attribute 'mro',因為無法進(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 冷門魔術(shù)方法小結(jié)的文章就介紹到這了,更多相關(guān)Python 冷門魔術(shù)方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
windows下添加Python環(huán)境變量的方法匯總
默認(rèn)情況下,在windows下安裝python之后,系統(tǒng)并不會自動添加相應(yīng)的環(huán)境變量。此時不能在命令行直接使用python命令。今天我們就來看下,如何簡單快捷的在windows下添加Python環(huán)境變量2018-05-05
pytorch中的weight-initilzation用法
這篇文章主要介紹了pytorch中的weight-initilzation用法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-06-06
pandas DataFrame tail的使用小結(jié)
本文主要介紹了pandas DataFrame tail的使用小結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-05-05
python之no module named xxxx以及虛擬環(huán)境配置過程
在Python開發(fā)過程中,經(jīng)常會遇到環(huán)境配置和包管理的問題,主要原因包括未安裝所需包或使用虛擬環(huán)境導(dǎo)致的,通過pip install命令安裝缺失的包是解決問題的一種方式,此外,使用虛擬環(huán)境,例如PyCharm支持的Virtualenv,可以為每個項目創(chuàng)建獨立的運行環(huán)境2024-10-10
pytorch部署到j(luò)upyter中的問題及解決方案
這篇文章主要介紹了pytorch部署到j(luò)upyter中,在這里需要注意我再輸入的時候出現(xiàn)了一些無法定位的提示,但是我的電腦沒有影響使用jupyter,還是可以使用jupyter并且可以import torch,本文給大家講解的非常詳細(xì),需要的朋友參考下吧2022-05-05
Python結(jié)合wxPython實現(xiàn)AI繪圖提示詞生成器
這篇文章主要為大家詳細(xì)介紹了Python如何基于wxPython開發(fā)一個AI繪圖提示詞生成器,專門用于幫助用戶快速構(gòu)建和管理Stable?Diffusion、Midjourney等AI繪圖工具的提示詞,感興趣的小伙伴可以了解下2025-12-12
tensorflow使用freeze_graph.py將ckpt轉(zhuǎn)為pb文件的方法
這篇文章主要介紹了tensorflow使用freeze_graph.py將ckpt轉(zhuǎn)為pb文件的方法,需要的朋友可以參考下2020-04-04
Python 如何實時向文件寫入數(shù)據(jù)(附代碼)
這篇文章主要介紹了Python 如何實時向文件寫入數(shù)據(jù)(附代碼),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07

