Python中的魔法方法
python中的魔法方法是一些可以讓你對類別添加「魔法」的特殊方法,它們經常是兩個下劃線包圍來命名的。
Python的魔法方法,也稱為dunder(雙底線)方法。大多數的時候,我們將它們用於簡單的事情,例如建構函數(init)、字串表示(str, repr)或算術運算子(add/mul)。其實還有許多你可能沒聽過的但是卻很好用的方法,在這篇文章中,我們將整理這些魔法方法!
##迭代器的大小
#我們都知道__len__方法,可以用它在容器類別上實作len()函數。但是,如果您想要取得實作迭代器的類別物件的長度怎麼辦?it = iter(range(100)) print(it.__length_hint__()) # 100 next(it) print(it.__length_hint__()) # 99 a = [1, 2, 3, 4, 5] it = iter(a) print(it.__length_hint__()) # 5 next(it) print(it.__length_hint__()) # 4 a.append(6) print(it.__length_hint__()) # 5
大部分很少看到的神奇方法都與元程式設計有關,雖然元程式設計可能不是我們每天都需要使用的東西,但有一些方便的技巧可以使用它。length_hint must return an integer (else a TypeError is raised) or NotImplemented, and is not required to be accurate. It may return a value that is either be accurate. larIt may return a value that is either be accurate. larIt may return a value that is either be accurate. the actual size of the container. A return value of NotImplemented indicates that there is no finite length estimate. It may not return a negative value (else# a ValueError is#ised).#". #元程式設計
一個這樣的技巧是使用__init_subclass__作為擴展基類功能的快捷方式,而不必處理元類: class Pet:
def __init_subclass__(cls, /, default_breed, **kwargs):
super().__init_subclass__(**kwargs)
cls.default_breed = default_breed
class Dog(Pet, default_name="German Shepherd"):
pass
登入後複製
上面的代碼我們向基類添加關鍵字參數,該參數可以在定義子類別時設定。在實際用例中可能會在想要處理提供的參數而不僅僅是賦值給屬性的情況下使用此方法。 看起來非常晦澀並且很少會用到,但其實你可能已經遇到過很多次了,因為它一般都是在構建API時使用的,例如在SQLAlchemy或Flask Views中都使用到了。 另一個元類別的神奇方法是__call__。這個方法允許自訂呼叫類別實例時發生的事情:class Pet: def __init_subclass__(cls, /, default_breed, **kwargs): super().__init_subclass__(**kwargs) cls.default_breed = default_breed class Dog(Pet, default_name="German Shepherd"): pass
class CallableClass: def __call__(self, *args, **kwargs): print("I was called!") instance = CallableClass() instance() # I was called!
class NoInstances(type): def __call__(cls, *args, **kwargs): raise TypeError("Can't create instance of this class") class SomeClass(metaclass=NoInstances): @staticmethod def func(x): print('A static method') instance = SomeClass() # TypeError: Can't create instance of this class
class Singleton(type): def __init__(cls, *args, **kwargs): cls.__instance = None super().__init__(*args, **kwargs) def __call__(cls, *args, **kwargs): if cls.__instance is None: cls.__instance = super().__call__(*args, **kwargs) return cls.__instance else: return cls.__instance class Logger(metaclass=Singleton): def __init__(self): print("Creating global Logger instance")
class Document: def __init__(self, text): self.text = text bare_document = Document.__new__(Document) print(bare_document.text) # AttributeError: 'Document' object has no attribute 'text' setattr(bare_document, "text", "Text of the document")
class Document: def __init__(self, text): self.text = text @classmethod def from_file(cls, file): # Alternative constructor d = cls.__new__(cls) # Do stuff... return d
class String: def __init__(self, value): self._value = str(value) def custom_operation(self): pass def __getattr__(self, name): return getattr(self._value, name) s = String("some text") s.custom_operation() # Calls String.custom_operation() print(s.split()) # Calls String.__getattr__("split") and delegates to str.split # ['some', 'text'] print("some text" + "more text") # ... works print(s + "more text") # TypeError: unsupported operand type(s) for +: 'String' and 'str'
自省(introspection)
最后一个与元编程相关的方法是__getattribute__。它一个看起来非常类似于前面的__getattr__,但是他们有一个细微的区别,__getattr__只在属性查找失败时被调用,而__getattribute__是在尝试属性查找之前被调用。
所以可以使用__getattribute__来控制对属性的访问,或者你可以创建一个装饰器来记录每次访问实例属性的尝试:
def logger(cls): original_getattribute = cls.__getattribute__ def getattribute(self, name): print(f"Getting: '{name}'") return original_getattribute(self, name) cls.__getattribute__ = getattribute return cls @logger class SomeClass: def __init__(self, attr): self.attr = attr def func(self): ... instance = SomeClass("value") instance.attr # Getting: 'attr' instance.func() # Getting: 'func'
装饰器函数logger 首先记录它所装饰的类的原始__getattribute__方法。然后将其替换为自定义方法,该方法在调用原始的__getattribute__方法之前记录了被访问属性的名称。
魔法属性
到目前为止,我们只讨论了魔法方法,但在Python中也有相当多的魔法变量/属性。其中一个是__all__:
# some_module/__init__.py __all__ = ["func", "some_var"] some_var = "data" some_other_var = "more data" def func(): return "hello" # ----------- from some_module import * print(some_var) # "data" print(func()) # "hello" print(some_other_var) # Exception, "some_other_var" is not exported by the module
这个属性可用于定义从模块导出哪些变量和函数。我们创建了一个Python模块…/some_module/单独文件(__init__.py)。在这个文件中定义了2个变量和一个函数,只导出其中的2个(func和some_var)。如果我们尝试在其他Python程序中导入some_module的内容,我们只能得到2个内容。
但是要注意,__all__变量只影响上面所示的* import,我们仍然可以使用显式的名称导入函数和变量,比如import some_other_var from some_module。
另一个常见的双下划线变量(模块属性)是__file__。这个变量标识了访问它的文件的路径:
from pathlib import Path print(__file__) print(Path(__file__).resolve()) # /home/.../directory/examples.py # Or the old way: import os print(os.path.dirname(os.path.abspath(__file__))) # /home/.../directory/
这样我们就可以结合__all__和__file__,可以在一个文件夹中加载所有模块:
# Directory structure: # . # |____some_dir # |____module_three.py # |____module_two.py # |____module_one.py from pathlib import Path, PurePath modules = list(Path(__file__).parent.glob("*.py")) print([PurePath(f).stem for f in modules if f.is_file() and not f.name == "__init__.py"]) # ['module_one', 'module_two', 'module_three']
最后一个我重要的属性是的是__debug__。它可以用于调试,但更具体地说,它可以用于更好地控制断言:
# example.py def func(): if __debug__: print("debugging logs") # Do stuff... func()
如果我们使用python example.py正常运行这段代码,我们将看到打印出“调试日志”,但是如果我们使用python -O example.py,优化标志(-O)将把__debug__设置为false并删除调试消息。因此,如果在生产环境中使用-O运行代码,就不必担心调试过程中被遗忘的打印调用,因为它们都不会显示。
创建自己魔法方法?
我们可以创建自己的方法和属性吗?是的,你可以,但你不应该这么做。
双下划线名称是为Python语言的未来扩展保留的,不应该用于自己的代码。如果你决定在你的代码中使用这样的名称,那么将来如果它们被添加到Python解释器中,这就与你的代码不兼容了。所以对于这些方法,我们只要记住和使用就好了。
以上是Python中的魔法方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

PHP和Python各有優劣,選擇取決於項目需求和個人偏好。 1.PHP適合快速開發和維護大型Web應用。 2.Python在數據科學和機器學習領域佔據主導地位。

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

在CentOS系統上啟用PyTorchGPU加速,需要安裝CUDA、cuDNN以及PyTorch的GPU版本。以下步驟將引導您完成這一過程:CUDA和cuDNN安裝確定CUDA版本兼容性:使用nvidia-smi命令查看您的NVIDIA顯卡支持的CUDA版本。例如,您的MX450顯卡可能支持CUDA11.1或更高版本。下載並安裝CUDAToolkit:訪問NVIDIACUDAToolkit官網,根據您顯卡支持的最高CUDA版本下載並安裝相應的版本。安裝cuDNN庫:前

Docker利用Linux內核特性,提供高效、隔離的應用運行環境。其工作原理如下:1. 鏡像作為只讀模板,包含運行應用所需的一切;2. 聯合文件系統(UnionFS)層疊多個文件系統,只存儲差異部分,節省空間並加快速度;3. 守護進程管理鏡像和容器,客戶端用於交互;4. Namespaces和cgroups實現容器隔離和資源限制;5. 多種網絡模式支持容器互聯。理解這些核心概念,才能更好地利用Docker。

MinIO對象存儲:CentOS系統下的高性能部署MinIO是一款基於Go語言開發的高性能、分佈式對象存儲系統,與AmazonS3兼容。它支持多種客戶端語言,包括Java、Python、JavaScript和Go。本文將簡要介紹MinIO在CentOS系統上的安裝和兼容性。 CentOS版本兼容性MinIO已在多個CentOS版本上得到驗證,包括但不限於:CentOS7.9:提供完整的安裝指南,涵蓋集群配置、環境準備、配置文件設置、磁盤分區以及MinI

在CentOS系統上進行PyTorch分佈式訓練,需要按照以下步驟操作:PyTorch安裝:前提是CentOS系統已安裝Python和pip。根據您的CUDA版本,從PyTorch官網獲取合適的安裝命令。對於僅需CPU的訓練,可以使用以下命令:pipinstalltorchtorchvisiontorchaudio如需GPU支持,請確保已安裝對應版本的CUDA和cuDNN,並使用相應的PyTorch版本進行安裝。分佈式環境配置:分佈式訓練通常需要多台機器或單機多GPU。所

在CentOS系統上安裝PyTorch,需要仔細選擇合適的版本,並考慮以下幾個關鍵因素:一、系統環境兼容性:操作系統:建議使用CentOS7或更高版本。 CUDA與cuDNN:PyTorch版本與CUDA版本密切相關。例如,PyTorch1.9.0需要CUDA11.1,而PyTorch2.0.1則需要CUDA11.3。 cuDNN版本也必須與CUDA版本匹配。選擇PyTorch版本前,務必確認已安裝兼容的CUDA和cuDNN版本。 Python版本:PyTorch官方支

在CentOS上更新PyTorch到最新版本,可以按照以下步驟進行:方法一:使用pip升級pip:首先確保你的pip是最新版本,因為舊版本的pip可能無法正確安裝最新版本的PyTorch。 pipinstall--upgradepip卸載舊版本的PyTorch(如果已安裝):pipuninstalltorchtorchvisiontorchaudio安裝最新
