日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

【Python基础】Python中必须知道的5对魔术方法

發布時間:2025/3/8 python 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Python基础】Python中必须知道的5对魔术方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文作者:Yong Cui

翻譯:Lemon

譯文出品:Python數據之道

Photo by?Liz Hixon?on?Unsplash

簡介

在使用Python命名函數時,我們可以使用下劃線以及字母和數字。在單詞之間使用下劃線時,它們沒有多大意義,它們只是通過在單詞之間創建空格來提高可讀性。這就是蛇形命名方式。例如,?calculate_mean_score?比?calculatemeanscore?更易于閱讀。您可能已經知道,除了這種使用下劃線的常用方式之外,我們還為函數名稱加上一個或兩個下劃線(例如,?_func,?__func),以表示這些函數供類或模塊內的私有使用。沒有下劃線前綴的名稱被認為是公共API。

下劃線在函數命名中的另一種用法是魔術方法(magic methods),也稱為特殊方法。具體來說,我們在函數名稱之前放置兩個下劃線,在函數名稱之后放置兩個下劃線-類似于?__func__。由于使用了雙下劃線,因此某些人將特殊方法稱為 “dunder方法” 或簡稱為 “dunders” 。在本文中,我想回顧五對緊密相關的常用魔術方法,每對方法代表一個 Python 概念。

「Python數據之道」注:dunder 是 double underscore 的縮寫,即雙下劃線。

1. 實例化:?__new__?和?__init__

在學習了 Python 數據結構的基礎知識(例如字典,列表)之后,您應該已經看到了一些定義自定義類的示例,在這些示例中,您第一次接觸到了魔術方法?__init__。此方法用于定義實例對象的初始化行為。具體來說,在?__init__?方法中,您想要為創建的實例對象設置初始屬性。這是一個簡單的示例:

class Product:def __init__(self, name, price):self.name = nameself.price = price

當我們使用?__init__方法時,我們不會直接調用它。取而代之的是,?__init__方法成為該類的構造函數方法的構建基礎,該類的構造函數與?__init__方法具有相同的功能簽名。例如,要創建一個新的?Product?實例,請使用以下代碼:

product = Product("Vacuum", 150.0)

與?__init__方法最接近的是?__new__?方法,我們通常不會在自定義類中實現該方法。本質上,?__new__?方法實際上創建了實例對象,該實例對象被傳遞給?__init__?方法以完成初始化過程。

換句話說,構造新的實例對象(稱為實例化的過程)涉及依次調用?__new__?和?__init__方法。

以下代碼展示了這樣的一系列反應:

>>> class Product: ... def __new__(cls, *args): ... new_product = object.__new__(cls) ... print("Product __new__ gets called") ... return new_product ... ... def __init__(self, name, price): ... self.name = name ... self.price = price ... print("Product __init__ gets called") ... >>> product = Product("Vacuum", 150.0) Product __new__ gets called Product __init__ gets called

2. 字符串(String)的表現形式:?__repr__?和?__str__

這兩種方法對于為自定義類設置字符串表現形式都很重要。在解釋它們之前,讓我們快速看一下下面的實現過程:

class Product:def __init__(self, name, price):self.name = nameself.price = pricedef __repr__(self):return f"Product({self.name!r}, {self.price!r})"def __str__(self):return f"Product: {self.name}, ${self.price:.2f}"

__repr__?方法應該返回一個字符串,該字符串顯示如何創建實例對象。具體來說,可以將該字符串傳遞給?eval()來重新構造實例對象。以下代碼段向您展示了這樣的操作:

>>> product = Product("Vacuum", 150.0) >>> repr(product) "Product('Vacuum', 150.0)" >>> evaluated = eval(repr(product)) >>> type(evaluated) <class '__main__.Product'>

__str__?方法可以返回有關實例對象的更多描述。應該注意的是,?print()?函數使用?__str__方法來顯示與實例相關的信息,如下所示:

>>> print(product) Product: Vacuum, $150.00

盡管這兩種方法都應返回字符串,但是?__repr__?方法通常是供開發人員使用的,因此我們希望顯示實例化信息,而?__str__?方法是針對常規用戶的,因此我們希望顯示更多的信息。

3. 迭代:?__iter__?和?__next__

我們可以使代碼自動化的一個關鍵操作是為我們重復執行一項工作,該工作的實現涉及到 for 循環作為邏輯流程。就相關對象而言,它可以在 for 循環中使用。for 循環的最基本形式如下所示:

for item in iterable:# Operations go here

在底層,可迭代對象轉換為迭代器,該迭代器為每個循環顯示可迭代對象。一般來說,迭代器是 Python 對象,可用于渲染要迭代的變量。轉換是通過實現?__iter__?特殊方法來完成的。另外,檢索迭代器的下一項涉及?__next__?特殊方法的實現。讓我們繼續前面的示例,并使我們的 Product 類作為 for 循環中的迭代器工作:

>>> class Product: ... def __init__(self, name, price): ... self.name = name ... self.price = price ... ... def __str__(self): ... return f"Product: {self.name}, ${self.price:.2f}" ... ... def __iter__(self): ... self._free_samples = [Product(self.name, 0) for _ in range(3)] ... print("Iterator of the product is created.") ... return self ... ... def __next__(self): ... if self._free_samples: ... return self._free_samples.pop() ... else: ... raise StopIteration("All free samples have been dispensed.") ... >>> product = Product("Perfume", 5.0) >>> for i, sample in enumerate(product, 1): ... print(f"Dispense the next sample #{i}: {sample}") ... Iterator of the product is created. Dispense the next sample #1: Product: Perfume, $0.00 Dispense the next sample #2: Product: Perfume, $0.00 Dispense the next sample #3: Product: Perfume, $0.00

如上所示,我們創建了一個對象列表,該對象列表在?__iter__?方法中保存了免費樣本 (free samples),這些樣本為自定義類實例提供了迭代器。為了實現迭代行為,我們通過提供免費樣本列表中的對象來實現?__next__?方法。當我們用完免費樣本時,迭代結束。

4. 上下文管理器:?__enter__?和?__exit__

當我們使用 Python 處理文件對象時,你遇到的最常見的語法可能是這樣的:

with open('filename.txt') as file:# Your file operations go here

with?語句的使用被稱為上下文管理器技術。具體來說,在上面的文件操作示例中,?with?語句將為文件對象創建一個上下文管理器,并且在文件操作之后,上下文管理器將幫助我們關閉文件對象,以便共享資源(即文件) 可以用于其他進程。

因此,通常來說,上下文管理器是 Python 對象,它們為我們管理共享資源,例如打開和關閉。沒有它們,我們必須手動管理它們,這很容易出錯。

為了通過自定義類實現這種行為,我們的類需要實現?__enter__?和?__exit__?方法。?__enter__?方法設置了上下文管理器,該上下文管理器為我們進行操作準備了所需的資源,而?__exit__?方法則是清理應釋放的所有已使用資源,以使其可用。讓我們考慮下面的簡單示例,其中包含先前的 “ Product” 類:

>>> class Product: ... def __init__(self, name, price): ... self.name = name ... self.price = price ... ... def __str__(self): ... return f"Product: {self.name}, ${self.price:.2f}" ... ... def _move_to_center(self): ... print(f"The product ({self}) occupies the center exhibit spot.") ... ... def _move_to_side(self): ... print(f"Move {self} back.") ... ... def __enter__(self): ... print("__enter__ is called") ... self._move_to_center() ... ... def __exit__(self, exc_type, exc_val, exc_tb): ... print("__exit__ is called") ... self._move_to_side() ... >>> product = Product("BMW Car", 50000) >>> with product: ... print("It's a very good car.") ... __enter__ is called The product (Product: BMW Car, $50000.00) occupies the center exhibit spot. It's a very good car. __exit__ is called Move Product: BMW Car, $50000.00 back.

如你所見,當實例對象嵌入在 with 語句中時,將調用?__enter__?方法。當在 with 語句中完成該操作時,將調用?__exit__?方法。

但是,應該注意,我們可以實現?__enter__和?__exit__方法來創建上下文管理器。使用上下文管理器“裝飾器”函數,可以更輕松地完成此操作。

5. 更精細的屬性訪問控制:?__getattr__?和?__setattr__

如果您有其他語言的編程經驗,則可能已習慣于為實例屬性設置顯式的 getter 和 setter 。在 Python 中,我們不需要為每個單獨的屬性使用這些訪問控制技術。但是,有可能通過實現?__getattr__和?__setattr__方法來進行控制。具體來說,訪問實例對象的屬性時將調用?__getattr__?方法,而當我們設置實例對象的屬性時將調用?__setattr__?方法。

>>> class Product: ... def __init__(self, name): ... self.name = name ... ... def __getattr__(self, item): ... if item == "formatted_name": ... print(f"__getattr__ is called for {item}") ... formatted = self.name.capitalize() ... setattr(self, "formatted_name", formatted) ... return formatted ... else: ... raise AttributeError(f"no attribute of {item}") ... ... def __setattr__(self, key, value): ... print(f"__setattr__ is called for {key!r}: {value!r}") ... super().__setattr__(key, value) ... >>> product = Product("taBLe") __setattr__ is called for 'name': 'taBLe' >>> product.name 'taBLe' >>> product.formatted_name __getattr__ is called for formatted_name __setattr__ is called for 'formatted_name': 'Table' 'Table' >>> product.formatted_name 'Table'

每當我們嘗試設置對象的屬性時,都會調用?__setattr__?方法。若要正確使用它,必須通過使用?super()?使用超類方法。否則,它將陷入無限遞歸。

設置好 formatted_name 屬性后,該屬性將成為?__dict__?對象的一部分,因此不會調用?__getattr__。

附帶說明一下,還有另一種與訪問控制緊密相關的特殊方法稱為?__getattribute__,它類似于?__getattr__,但是每次訪問屬性時都會被調用。在這方面,它類似于?__setattr__,同樣,你應使用super()實現?__getattribute__?方法,以避免無限遞歸錯誤。

小結

在本文中,我們回顧了五對重要的特殊方法,通過它們我們學習了有關的五個 Python 概念。我希望您對這些概念以及如何在自己的 Python 項目中使用特殊方法有更好的理解。

原文作者:Yong Cui

來源:

https://medium.com/better-programming/5-pairs-of-magic-methods-in-python-you-should-know-f98f0e5356d6

---------End---------

往期精彩回顧適合初學者入門人工智能的路線及資料下載機器學習及深度學習筆記等資料打印機器學習在線手冊深度學習筆記專輯《統計學習方法》的代碼復現專輯 AI基礎下載機器學習的數學基礎專輯獲取一折本站知識星球優惠券,復制鏈接直接打開:https://t.zsxq.com/662nyZF本站qq群704220115。加入微信群請掃碼進群(如果是博士或者準備讀博士請說明):

總結

以上是生活随笔為你收集整理的【Python基础】Python中必须知道的5对魔术方法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。