當前位置:
首頁 > 知識 > Python中的 @property特性

Python中的 @property特性



你將了解Python中的 @property特性, 以pythonic的方式使用getter和setter。

目錄表



  • 從一個例子開始



  • 使用 Getter 和 Setter



  • @property的力量



  • 深入理解Property

Python有一個很棒的概念,叫做property,它使面向對象的程序員的生活更加簡單。

在定義和研究@property是什麼之前,讓我們先直觀感受下為什麼首先應該使用它。

從一個例子開始

我們假設你決定創建一個可以以攝氏度存儲溫度的類[1],它還將實現一個將溫度轉換為華氏度的方法。一種方法是像下面這樣做。



我們可以使用這個類創建對象,並按照我們的意願操作其屬性

temperature

。你可以在Python shell上試試這些操作。



在轉換成華氏溫度時,由於浮點運算錯誤(請在Python解釋器中嘗試

1.1 + 2.2

),小數點多了一位。

當我們賦值或檢索任何對象屬性像

temperature

時,如上面所示,Python都會在該對象的

__dict__

字典中搜索它。

因此,

man.temperature

在內部會變成

man.__dict__["temperature"]

現在,讓我們進一步假設我們的類在客戶中很受歡迎,他們開始在自己的程序中使用它。他們對這個對象做了各種各樣的賦值操作。



有一天,一個值得信賴的客戶來找我們,建議溫度不能低於-273攝氏度(熱力學專業的學生可能會說實際上是-273.15攝氏度),也被稱為絕對零度。他還要求我們實現這個值約束。作為一家追求客戶滿意的公司,我們很高興地採納了這個建議,並發布了1.01版本(對現有的類進行升級)。

使用Getter和Setter


上述對值進行約束的一個明顯解決方案是隱藏屬性

temperature

(使其私有)並定義新的 getter 和 setter 介面來操作它。可以按照下面這樣做。

從上面可以看出,我們定義了

get_temperature()

set_temperature()

兩個新方法,並且用

_temperature

替換了

temperature

。在Python中,開頭的下劃線 (_) 用於表示私有變數。

這次更新成功地實現了新的限制。我們沒法再將溫度設置在-273度以下。

請注意,Python中不存在私有變數,但還是有一些簡單的準則可以遵循。Python語言本身並不會做限制。





但這並不是什麼大問題。上述更新的一個大問題是,所有在其程序中實現我們前面的類的客戶都必須修改他們的代碼,將

obj.temperature

修改為 

obj.get_temperature()

,並且將像 

obj.temperature = val 

的所有賦值語句修改為

obj.set_temperature(val)

這種重構可能會給客戶帶來數十多萬行代碼的麻煩。

總之,我們的新更新不向後兼容。這時property就派上用場了。

@property的力量



處理上述問題的Pythonic的方法是使用property。以下是我們如何實現它。





然後,在shell中運行以下代碼並注意觀察。




我們在

get_temperature()

set_temperature()

中添加了一個

print()

函數,來清楚地觀察它們是否正在執行。

代碼的最後一行創建了一個property對象

temperature

。簡單地說,property將一些代碼( 

get_temperature 

set_temperature

)附加到成員屬性訪問中(

temperature

)。

任何檢索

temperature

值的代碼都將自動調用

get_temperature()

,而不是使用字典(__dict__)進行查找。類似地,任何對

temperature

賦值的代碼都會自動調用

set_temperature()

。這是Python中一個很酷的特性。

我們可以看到上面的

set_temperature()

即使在創建對象時也被調用。

你能猜到這是為什麼嗎?

原因是在創建對象時,

__init__() 

方法被調用。這個方法有

self.temperature = temperature

這行代碼,所以賦值時會自動調用

set_temperature()





類似地,任何訪問,比如

c.temperature

,都會自動調用

get_temperature()

。這就是property的作用。這裡有更多的幾個例子。



通過使用 property,可以看到,我們修改了類並實現了對值的約束,而不需要對客戶代碼進行任何更改。因此,我們的實現是向後兼容的,皆大歡喜。

最後請注意,實際的溫度值存儲在私有變數

_temperature

中。屬性

temperature

是一個property對象,它為這個私有變數提供介面。

深入理解 Property



在Python中,

property()

是一個內置函數,用於創建和返回一個property對象。這個函數的簽名是:





其中,

fget

是獲取屬性值的函數,

fset

是設置屬性值的函數,

fdel

是刪除屬性的函數,

doc

是字元串(像注釋一樣)。從上述實現中可以看出,這些函數參數是可選的。因此,可以按照以下方式創建property對象。


property對象有三個方法,

getter()

setter()

deleter()

,用於後續指定

fget

fset

fdel

。這意味著本行代碼



可以分解為



這兩段代碼是等價的。

熟悉

Python中的裝飾器[2]

的程序員可能會意識到,上面的構造可以實現為裝飾器。

我們可以繼續,不去定義

get_temperature 

set_temperature

名稱,因為它們是不必要的,並且會污染類命名空間。為此,我們在定義

getter

setter

函數時重用了名稱

temperature

。這就是它實現的方式。





上述實現是既簡單又推薦使用的創建property的方法。當你在Python中尋找property時,你很可能會遇到這些類型的構造。

好了,今天就到這裡。

相關鏈接:


[1]——

https://www.programiz.com/python-programming/class


[2]——

https://www.programiz.com/python-programming/decorator





英文原文:https://www.programiz.com/python-programming/property  
 譯者:野生大熊貓  


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python程序員 的精彩文章:

Bash & Git 速查表

TAG:Python程序員 |