python使用property完成數(shù)據(jù)隱藏封裝與校驗(yàn)
禁止隨意設(shè)置屬性
需求
考慮這樣一種情況,在某一個(gè)類中,有一個(gè)屬性我們不希望別人隨便設(shè)置,因?yàn)檫@可能會(huì)造成很大的麻煩:
class Rectangle: def __init__(self, width, height): self.width = width self.height = height def calculate_area(self): return self.width * self.height r = Rectangle(3, 4) print(r.calculate_area())
在這種情況下,長度和寬度都應(yīng)該是數(shù)字類型的,而如果有人在這個(gè)過程中修改了這個(gè)屬性,那么就會(huì)導(dǎo)致錯(cuò)誤。
r = Rectangle(3, 4) r.width = "3" print(r.calculate_area()) # 結(jié)果為3333,明顯不是我們希望的結(jié)果
私有屬性
為了避免他人隨意訪問,我們可以將其設(shè)置為私有屬性,通常可以添加1個(gè)或者2個(gè)下劃線。
class Rectangle: def __init__(self, width, height): # 一個(gè)下劃線通常表明了,這個(gè)屬性不應(yīng)該隨意使用,但是不起實(shí)際作用 self._width = width # 兩個(gè)下劃線表明了,這個(gè)屬性會(huì)觸發(fā)名稱重整,但是也并非真正的私有 self.__height = height r = Rectangle(3, 4) print(r._width) # 雙下劃線最終會(huì)重整為_類名__屬性名的形式 print(r._Rectangle__height)
需要注意的是,由于python中沒有真正的私有屬性,所以,這兩種設(shè)置方法都不能完全起到作用,但是一般而言,兩個(gè)下劃線是更好的,因?yàn)榭梢杂|發(fā)名稱重整。
提供訪問方法
在這種情況下,為了避免他人隨意設(shè)置屬性,因此需要提供專門的訪問方法。
class Rectangle: def __init__(self, width, height): self.set_width(width) self.set_height(height) def set_width(self, width): if not isinstance(width, (int, float)): raise ValueError("width must be a number.") if width <= 0: raise ValueError("width must be greater than 0.") self.__width = width def set_height(self, height): if not isinstance(height, (int, float)): raise ValueError("height must be a number.") if height <= 0: raise ValueError("height must be greater than 0.") self.__height = height def get_width(self): return self.__width def get_height(self): return self.__height r = Rectangle(3, 4) # 此時(shí)需要通過專門的方法進(jìn)行訪問 print(r.get_width()) # 非法的設(shè)置不再被允許 r.set_width("3")
但是這樣的使用方法并不方便,因此,在python中,一個(gè)更好的使用方法是通過property。
property的詳細(xì)介紹
基本語法
基本語法實(shí)現(xiàn)是通過property的內(nèi)置函數(shù)完成的
class MyClass: def __init__(self, value): self.value = value # get方法 def get_value(self): return self.__value # set方法 def set_value(self, value): if value < 0: raise ValueError("value must be non-negative.") self.__value = value # del方法 def del_value(self): print("value is being deleted.") del self.__value # property創(chuàng)建 value = property(get_value, set_value, del_value) mc = MyClass(20241120) print(mc.value)
使用裝飾器
class MyClass: def __init__(self, value): self.value = value @property def value(self): return self.__value @value.setter def value(self, value): if value < 0: raise ValueError("value must be non-negative.") self.__value = value @value.deleter def value(self): print("value is being deleted.") del self.__value
與基本語法的版本效果是相同的
常見應(yīng)用
數(shù)據(jù)隱藏與封裝
property裝飾器允許像訪問和操作普通一樣屬性進(jìn)行操作
class Rectangle: def __init__(self, width, height): self.width = width self.height = height @property def width(self): return self.__width @width.setter def width(self, value): if not isinstance(value, (int, float)): raise ValueError("width must be a number.") if value <= 0: raise ValueError("width must be greater than 0.") self.__width = value @property def height(self): return self.__height @height.setter def height(self, value): if not isinstance(value, (int, float)): raise ValueError("height must be a number.") if value <= 0: raise ValueError("height must be greater than 0.") self.__height = value r = Rectangle(3, 4) print(r.width) r.width = "3"
設(shè)置只讀屬性
通過property,可以設(shè)置一個(gè)屬性只允許讀取,不允許修改
class Person: def __init__(self, name): self.__name = name @property def name(self): return self.__name # 初始化的時(shí)候可以設(shè)置名字 p = Person("sagegrass") # 名字可以正常被訪問 print(p.name) # 名字不可以被修改,AttributeError: can't set attribute 'name' p.name = "xxx"
一般來說,這樣設(shè)置已經(jīng)足夠保證屬性只讀,但是極特殊的情況下,仍然可以通過p._Person__name進(jìn)行修改,
不過通常無需額外關(guān)注這一問題。
動(dòng)態(tài)計(jì)算
關(guān)于一開始的例子,我們使用calculate_area進(jìn)行面積的計(jì)算,但是,通過property就可以將area設(shè)置為一個(gè)屬性,進(jìn)行動(dòng)態(tài)的計(jì)算
class Rectangle: def __init__(self, width, height): self.width = width self.height = height def calculate_area(self): return self.width * self.height
使用property屬性,修改為:
class Rectangle: def __init__(self, width, height): self.width = width self.height = height @property def area(self): return self.width * self.height r = Rectangle(3, 4) print(r.area) r.width = 5 print(r.area)
以上就是python使用property完成數(shù)據(jù)隱藏封裝與校驗(yàn)的詳細(xì)內(nèi)容,更多關(guān)于python property數(shù)據(jù)隱藏封裝與校驗(yàn)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python3.7 讀取音頻根據(jù)文件名生成腳本的代碼
這篇文章主要介紹了Python3.7 讀取音頻根據(jù)文件名生成字幕腳本的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04python使用正則表達(dá)式的search()函數(shù)實(shí)現(xiàn)指定位置搜索功能
SEARCH函數(shù),函數(shù)名。主要用來返回指定的字符串在原始字符串中首次出現(xiàn)的位置 ,從左到右查找,忽略英文字母的大小寫。接下來通過本文給大家介紹python使用正則表達(dá)式的search()函數(shù)實(shí)現(xiàn)指定位置搜索功能,需要的朋友一起看看吧2017-11-11Python實(shí)現(xiàn)刪除列表首元素的多種方式總結(jié)
在Python中,處理列表的操作是日常開發(fā)中不可避免的任務(wù)之一,其中,刪除列表中的元素是一個(gè)常見的需求,本文為大家整理了Python中刪除列表中的第一個(gè)元素的多種方法,需要的可以參考下2023-12-12python動(dòng)態(tài)參數(shù)用法實(shí)例分析
這篇文章主要介紹了python動(dòng)態(tài)參數(shù)用法,以實(shí)例形式較為詳細(xì)的分析了Python中動(dòng)態(tài)參數(shù)的功能及使用技巧,需要的朋友可以參考下2015-05-05python網(wǎng)絡(luò)爬蟲精解之pyquery的使用說明
PyQuery是一個(gè)類似于jQuery的解析網(wǎng)頁工具,使用lxml操作xml和html文檔,它的語法和jQuery很像。和XPATH,Beautiful Soup比起來,PyQuery更加靈活,提供增加節(jié)點(diǎn)的class信息,移除某個(gè)節(jié)點(diǎn),提取文本信息等功能2021-09-09Tornado Web服務(wù)器多進(jìn)程啟動(dòng)的2個(gè)方法
這篇文章主要介紹了Tornado Web服務(wù)器多進(jìn)程啟動(dòng)的2個(gè)方法,Tornado是一個(gè)用Ptyhon寫的WEB服務(wù)器,需要的朋友可以參考下2014-08-08python?tkinter自定義實(shí)現(xiàn)Expander控件
和其他成熟的GUI庫相比,tkinter的組件并不是太多,但在自定義組件這一點(diǎn)上,并不遜色于其他框架,下面小編就教大家如何自定義一個(gè)Expander控件吧2023-08-08Pytorch 如何實(shí)現(xiàn)LSTM時(shí)間序列預(yù)測
本文主要基于Pytorch深度學(xué)習(xí)框架,實(shí)現(xiàn)LSTM神經(jīng)網(wǎng)絡(luò)模型,用于時(shí)間序列的預(yù)測2021-05-05