python中@property注解的具體使用
一、@property核心定義
@property 是 Python 內(nèi)置的裝飾器,用于將類的方法轉(zhuǎn)換為屬性式訪問。它允許開發(fā)者將方法以屬性的形式調(diào)用(如 obj.attr 而非 obj.attr()),同時(shí)封裝屬性的讀?。╣etter)、賦值(setter)、刪除(deleter)邏輯,實(shí)現(xiàn)受控的屬性訪問(如數(shù)據(jù)驗(yàn)證、計(jì)算屬性、隱藏內(nèi)部變量)。
核心價(jià)值:
- 替代傳統(tǒng)的
get_x()/set_x()方法,讓屬性訪問更直觀、符合 Python 風(fēng)格; - 兼顧封裝性(隱藏內(nèi)部變量)和易用性(屬性式調(diào)用);
- 支持動態(tài)計(jì)算屬性(如根據(jù)其他屬性推導(dǎo)值)、數(shù)據(jù)校驗(yàn)(如限制屬性取值范圍)。
二、基礎(chǔ)用法
1. 只讀屬性(基礎(chǔ) getter)
最核心的用法是將方法轉(zhuǎn)為只讀屬性,適用于「計(jì)算屬性」(值由其他屬性推導(dǎo),無需手動賦值)。
示例:圓的面積計(jì)算
class Circle:
def __init__(self, radius: float):
self.radius = radius # 基礎(chǔ)屬性
@property
def area(self) -> float:
"""計(jì)算面積(只讀屬性),無需調(diào)用方法,直接訪問"""
return 3.1415926 * self.radius **2
# 使用:像訪問普通屬性一樣調(diào)用,無需加 ()
c = Circle(5)
print(c.area) # 輸出:78.539815
# 嘗試賦值會報(bào)錯(cuò)(只讀屬性)
# c.area = 100 # AttributeError: can't set attribute
2. 可寫屬性(setter 裝飾器)
通過 @屬性名.setter 裝飾器定義賦值邏輯,實(shí)現(xiàn)屬性的可控寫入(如數(shù)據(jù)驗(yàn)證)。
示例:年齡屬性的校驗(yàn)
class Person:
def __init__(self, name: str, age: int):
self.name = name
self._age = age # 下劃線前綴:約定俗成的「私有變量」(Python 無真正私有)
@property
def age(self) -> int:
"""getter:讀取年齡"""
return self._age
@age.setter
def age(self, value: int):
"""setter:賦值時(shí)驗(yàn)證數(shù)據(jù)合法性"""
# 類型校驗(yàn)
if not isinstance(value, int):
raise TypeError("年齡必須是整數(shù)")
# 范圍校驗(yàn)
if value < 0 or value > 150:
raise ValueError("年齡必須在 0-150 之間")
self._age = value
# 使用:賦值時(shí)自動觸發(fā) setter 校驗(yàn)
p = Person("Alice", 20)
print(p.age) # 20(觸發(fā) getter)
p.age = 25 # 合法賦值(觸發(fā) setter)
# p.age = "30" # 觸發(fā) TypeError
# p.age = 200 # 觸發(fā) ValueError
3. 可刪除屬性(deleter 裝飾器)
通過 @屬性名.deleter 裝飾器定義屬性刪除邏輯,適用于需要清理資源的場景。
示例:刪除年齡屬性
class Person:
# (繼承上面的 __init__、age getter/setter)
@age.deleter
def age(self):
"""deleter:刪除屬性時(shí)執(zhí)行的邏輯"""
print("刪除年齡屬性...")
del self._age
# 使用:刪除屬性觸發(fā) deleter
p = Person("Bob", 30)
del p.age # 輸出:刪除年齡屬性...
# 此時(shí)訪問 p.age 會報(bào)錯(cuò)(_age 已被刪除)
# print(p.age) # AttributeError: 'Person' object has no attribute '_age'
三、進(jìn)階用法
1. 與繼承結(jié)合:重寫父類的 property
子類可重寫父類的 @property 及其 setter/deleter,實(shí)現(xiàn)個(gè)性化邏輯。
class Student(Person):
@property
def age(self):
"""重寫 getter:添加學(xué)生年齡的額外提示"""
print(f"學(xué)生 {self.name} 的年齡:")
return super().age # 調(diào)用父類的 getter
@age.setter
def age(self, value):
"""重寫 setter:添加學(xué)生年齡的特殊校驗(yàn)"""
if value < 6 or value > 30:
raise ValueError("學(xué)生年齡應(yīng)在 6-30 之間")
super(Student, Student).age.fset(self, value) # 調(diào)用父類的 setter
# 測試
s = Student("Charlie", 18)
print(s.age) # 輸出:學(xué)生 Charlie 的年齡:18
s.age = 35 # 觸發(fā) ValueError
2. 緩存昂貴的計(jì)算屬性
對于計(jì)算耗時(shí)的屬性(如大數(shù)據(jù)處理、網(wǎng)絡(luò)請求),可結(jié)合 functools.lru_cache 緩存結(jié)果,避免重復(fù)計(jì)算。
import functools
class DataProcessor:
def __init__(self, raw_data: list[int]):
self.raw_data = raw_data
@property
@functools.lru_cache(maxsize=None) # 緩存方法結(jié)果
def processed_data(self) -> list[int]:
"""模擬昂貴的計(jì)算:僅首次調(diào)用時(shí)計(jì)算,后續(xù)直接返回緩存"""
print("執(zhí)行昂貴計(jì)算...")
return [x * 2 + 1 for x in self.raw_data]
# 測試
dp = DataProcessor([1, 2, 3, 4])
print(dp.processed_data) # 輸出:執(zhí)行昂貴計(jì)算... [3, 5, 7, 9]
print(dp.processed_data) # 直接返回緩存,無打印
3. 手動創(chuàng)建 property 對象(非裝飾器方式)
@property 本質(zhì)是語法糖,底層通過 property() 類實(shí)現(xiàn)。可手動創(chuàng)建 property 對象,效果與裝飾器一致:
class Person:
def __init__(self, age: int):
self._age = age
# 定義 getter/setter/deleter 方法
def get_age(self):
return self._age
def set_age(self, value):
if value < 0:
raise ValueError("年齡不能為負(fù)")
self._age = value
def del_age(self):
del self._age
# 手動創(chuàng)建 property 對象:property(fget, fset, fdel, doc)
age = property(get_age, set_age, del_age, "年齡屬性,支持校驗(yàn)")
# 使用方式與裝飾器一致
p = Person(20)
print(p.age) # 20
p.age = 25 # 合法
四、關(guān)鍵注意事項(xiàng)
1. 命名規(guī)范:避免變量名沖突
- 內(nèi)部存儲的變量建議用下劃線前綴(如
_age),與@property裝飾的方法名(如age)區(qū)分,避免無限遞歸:# 錯(cuò)誤示例:無限遞歸 class Person: def __init__(self, age): self.age = age # 賦值時(shí)觸發(fā) setter,setter 又賦值 self.age → 遞歸 @property def age(self): return self.age # 讀取時(shí)觸發(fā) getter,getter 又讀取 self.age → 遞歸 # 正確:內(nèi)部變量用 _age,property 方法用 age
2. 只讀屬性的限制
僅定義 @property(無 setter)的屬性是只讀的,嘗試賦值會拋出 AttributeError,適合純計(jì)算屬性。
五、@propertyvs 傳統(tǒng) getter/setter
| 特性 | @property | 傳統(tǒng) get_x()/set_x() |
|---|---|---|
| 調(diào)用方式 | obj.age(屬性式) | obj.get_age()(方法式) |
| 封裝性 | 隱藏內(nèi)部變量(如 _age) | 需手動約定命名規(guī)范 |
| 數(shù)據(jù)校驗(yàn) | 賦值時(shí)自動觸發(fā) setter 校驗(yàn) | 需手動調(diào)用 set_x() 校驗(yàn) |
| 代碼可讀性 | 更簡潔、符合 Python 風(fēng)格 | 冗余、不夠直觀 |
| 兼容性 | 僅新式類支持(Python 3 默認(rèn)) | 全版本兼容 |
六、適用場景總結(jié)
| 場景 | 推薦用法 |
|---|---|
| 計(jì)算屬性(如面積、總價(jià)) | 僅定義 @property(只讀) |
| 需要數(shù)據(jù)校驗(yàn)的屬性 | 定義 @property + @屬性名.setter |
| 需要清理資源的屬性 | 額外定義 @屬性名.deleter |
| 封裝內(nèi)部變量,對外提供統(tǒng)一訪問接口 | @property 替代手動 getter/setter |
| 復(fù)用屬性邏輯(多類共用) | 自定義描述符(而非 @property) |
七、總結(jié)
@property 是 Python 面向?qū)ο缶幊讨袑?shí)現(xiàn)屬性封裝的核心工具,它以簡潔的語法糖封裝了描述符協(xié)議,兼顧了「易用性」(屬性式訪問)和「封裝性」(受控的讀寫邏輯)。無論是實(shí)現(xiàn)計(jì)算屬性、數(shù)據(jù)校驗(yàn),還是隱藏內(nèi)部變量,@property 都是比傳統(tǒng) getter/setter 更優(yōu)雅的選擇,是 Python 開發(fā)者必須掌握的特性之一。
到此這篇關(guān)于python中@property注解的具體使用的文章就介紹到這了,更多相關(guān)python @property注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- python @property的用法及含義全面解析
- 介紹Python的@property裝飾器的用法
- 實(shí)例講解Python編程中@property裝飾器的用法
- python 中的@property的用法詳解
- Python 中@property的用法詳解
- Python @property裝飾器原理解析
- 詳解Python裝飾器之@property
- Python進(jìn)階之@property動態(tài)屬性的實(shí)現(xiàn)
- python裝飾器中@property屬性的使用解析
- Python @property原理解析和用法實(shí)例
- Python如何使用@property @x.setter及@x.deleter
- Python @property使用方法解析
- python中@Property屬性使用方法
相關(guān)文章
教你在Excel中調(diào)用Python腳本實(shí)現(xiàn)數(shù)據(jù)自動化處理的方法
Excel是全世界最流行的編程語言,Excel已經(jīng)可以實(shí)現(xiàn)編程語言的算法,因此它是具備圖靈完備性的,和JavaScript、Java、Python一樣,今天通過本文給大家介紹下Python數(shù)據(jù)自動化處理的相關(guān)知識,感興趣的朋友一起看看吧2022-02-02
Numpy之random函數(shù)使用學(xué)習(xí)
這篇文章主要介紹了Numpy之random使用學(xué)習(xí),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-01-01
python代碼打包到exe的實(shí)現(xiàn)示例
本文主要介紹了python代碼打包到exe的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-11-11
解決python 輸出到csv 出現(xiàn)多空行的情況
這篇文章主要介紹了解決python 輸出到csv 出現(xiàn)多空行的情況,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03
windows+vscode安裝paddleOCR運(yùn)行環(huán)境的步驟
這篇文章主要介紹了windows+vscode安裝paddleOCR運(yùn)行環(huán)境,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11
Python中處理表格數(shù)據(jù)的Tablib庫詳解
這篇文章主要介紹了Python中處理表格數(shù)據(jù)的Tablib庫詳解,Tablib 是一個(gè) MIT 許可的格式不可知的表格數(shù)據(jù)集庫,用 Python 編寫,它允許您導(dǎo)入、導(dǎo)出和操作表格數(shù)據(jù)集,需要的朋友可以參考下2023-08-08
Python關(guān)于時(shí)間序列calendar模塊的深入講解
calendar,是與日歷相關(guān)的模塊。calendar模塊文件里定義了很多類型,主要有Calendar,TextCalendar以及HTMLCalendar類型。其中,Calendar是TextCalendar與HTMLCalendar的基類2021-11-11

