python關鍵字之 property

2021-08-10 05:12:31 字數 4394 閱讀 4988

學習 python 的時候,經常遇見 @property 關鍵字,有時候讓我有點疑惑,所以寫下這篇部落格來記錄它。

在繫結屬性時,如果我們直接把屬性暴露出去,雖然寫起來很簡單,但是,沒辦法檢查引數,導致可以隨便更改屬性

舉個例子:

class celsius:

def __init__(self, temperature = 0):

self.temperature = temperature

def to_fahrenheit(self):

return (self.temperature * 1.8) + 32

>>>c = celsius()

>>>c.temperature = 37

37>>>c.to_fahreheit()

98.60000000000001

這顯然不好。為了限制 temperature 的範圍,可以通過乙個 set_temperature() 方法來設定溫度,再通過乙個 get_temperature() 來獲取溫度,這樣,在 set_temperature() 方法裡,就可以檢查引數:

class celsius:

def __init__(self, temperature = 0):

self.set_temperature(temperature)

def to_fahrenheit(self):

return (self.get_temperature() * 1.8) + 32

def get_temperature(self):

return self._temperature

def set_temperature(self, value):

if value < -273:

raise valueerror("temperature below -273 is not possible")

self._temperature = value

我們在上面設定了 get_termperature() 跟 set_temperature(),並且temperature 被 _temperature 所取代(在python 中,以 _ 開頭的變數都表示為私有變數)

>>> c = celsius(-277)

traceback (most recent call last):

...valueerror: temperature below -273 is not possible

>>> c = celsius(37)

>>> c.get_temperature()

37>>> c.set_temperature(10)

>>> c.set_temperature(-300)

traceback (most recent call last):

...valueerror: temperature below -273 is not possible

更新之後,我們不允許 _termperature 低於 -273。

但是這也帶來了大問題:上面的呼叫方法略顯複雜,沒有直接用屬性這麼直接簡單,這會造成很多多餘的**。

所以這裡就是 @property 可以大展身手的時候了

看下面的**:

class celsius:

def __init__(self, temperature = 0):

self.temperature = temperature

def to_fahrenheit(self):

return (self.temperature * 1.8) + 32

def c(self):

print("getting value")

return self._temperature

def set_temperature(self, value):

if value < -273:

raise valueerror("temperature below -273 is not possible")

print("setting value")

self._temperature = value

temperature = property(get_temperature,set_temperature)

對上面**的解釋:

(1)我們在 get_temperature() 和 set_temperature() 中新增了乙個 print() ,以清楚地看到它們什麼時候被執行。

(2)**的最後一行創造了乙個屬性物件:溫度。 簡單地說,屬性將一些**(get_temperature和set_temperature)附加到成員屬性訪問(temperature)。

(3)任何返回 temperature 的**將自動呼叫 get_temperature() 。 類似地,將 value 分配給 terperature 的任何**將自動呼叫 set_temperature()。

執行下面的**

>>> c = celsius()

>>> c.temperature

getting value

0

可能一開始看到結果的時候會有點不理解?為什麼會會返回getting value(證明呼叫了 set_temperature())?

原因是當建立物件時,__init__()方法被呼叫。 該方法具有 self.temperature = temperature。這個賦值自動呼叫set_temperature。

>>> c.temperature = 37

setting value

>>> c.to_fahrenheit()

getting value

98.60000000000001

最後注意,實際溫度值儲存在私有變數_temperature中。 

深入了解 property

在python中,property()是乙個內建函式,它建立並返回乙個屬性物件。 

property(fget=none, fset=none, fdel=none, doc=none)
其中,fget是獲取屬性值的函式,fset是設定屬性值的函式,fdel是刪除屬性的函式,doc是乙個字串。這些函式引數是可選的。

你也可以創造乙個 property()

>>> property()

乙個 property 物件有三個方法getter(),setter()和delete()來指定fget,fset和fdel。

temperature = property(get_temperature,set_temperature)
解釋:get_temperature 跟 set_temperature 是上面類的方法

我們可以不定義 get_temperature() 和 set_temperature() ,因為它們是不必要的。然而,我們在定義 getter 和 setter 函式時,可以重複使用 temperature

class celsius:

def __init__(self, temperature = 0):

self._temperature = temperature

def to_fahrenheit(self):

return (self.temperature * 1.8) + 32

@property

def temperature(self):

print("getting value")

return self._temperature

@temperature.setter

def temperature(self, value):

if value < -273:

raise valueerror("temperature below -273 is not possible")

print("setting value")

self._temperature = value

這種寫法是推薦使用的,並且也是比較簡單的。

總結:(1)如果乙個方法是用來獲取乙個值的話,那它就應該用 「@property」 來進行裝飾

(2)如果乙個方法是用來 setter 的話,它應該用 "@x.setter" 來進行裝飾( x 是函式的名字,如果函式被稱為「f」,我們將必須使用「@ f.setter」進行裝飾。)

學習 @property 參考了一些學習資料:

(1)(2)

python之with關鍵字

with表示式其實是try finally的簡寫形式。但是又不是全相同。格式with context as var pass 其中的context是乙個表示式,返回的是乙個物件,var用來儲存context表示式返回的物件,可以有單個或者多個返回值。但是with本身並沒有異常捕獲的功能,但是如果發生...

new關鍵字 this關鍵字 base關鍵字

使用new,所做的三件事 1.類是引用物件,引用物件是在堆中開闢空間 在堆中開闢空間 2.在開闢的堆空間中建立物件 3.呼叫物件的構建函式 4.隱藏父類成員 子類的成員可以與隱藏從父類繼承的成員,類似於重寫。public new void sayhello this關鍵字的使用 1.代表當前類的物件...

python基礎之關鍵字 三

開發人員在程式中自定義的一些符號和名稱 標示符是自己定義的,如變數名 函式名等 起乙個有意義的名字,盡量做到看一眼就知道是什麼意思 提高 可 讀性 比如 名字 就定義為 name 定義學生 用 student 小駝峰式命名法 lower camel case 第乙個單詞以小寫字母開始 第二個單詞的首...