06.16 Python 中屬性 Properties 和 Getters Setters 對比

Python 中屬性 Properties 和 Getters Setters 對比

在許多面向對象的編程語言中,使用 Getters 和 Setters 確保數據的封裝(data encapsulation)。他們使用公共的方法訪問私有屬性,這樣私有屬性就可以隱藏從而得到保護。

Getters 和 Setters


以下我們用 Java 式的寫法寫一個 Getters 和 Setters 的例子:

Python 中屬性 Properties 和 Getters Setters 對比

輸出:

Python 中屬性 Properties 和 Getters Setters 對比

你會注意到,c2.set_x(c.get_x() + 3) 這樣的寫法很彆扭,一點都不 Pythonic。

如果有一個公用的屬性 x,可以直接:

Python 中屬性 Properties 和 Getters Setters 對比

這樣既容易編寫代碼,又有很好的可讀性。

使用 Properties


我們重寫一下剛才的類:

Python 中屬性 Properties 和 Getters Setters 對比

這樣是不是就非常簡單了,但是,我們也丟失了數據封裝。

假如我們限定 x 的取值只能是 0到100,不用 Getters 和 Setters 怎麼實現呢?

Python 引入了屬性 Property,請看使用 Property 的類:

Python 中屬性 Properties 和 Getters Setters 對比

輸出:

Python 中屬性 Properties 和 Getters Setters 對比

使用 @property 裝飾器裝飾了一個獲取屬性值的方法。

另一個裝飾器 @x.setter 裝飾的是設置屬性的方法上面。例如如果方法名是 y,就應該使用 @y.setter 裝飾。

另外需要說明的是,在 __init__ 方法中,使用 self.x = x 同樣調用了被裝飾的方法,進行驗證。

還有就是兩個方法的名稱相同,只是參數不同,分別是 def x(self)和 def x(self, x)。

不使用裝飾器


可選的,不使用裝飾器,Python 提供了另一種方法定義屬性。

Python 中屬性 Properties 和 Getters Setters 對比

使用 x = property(get_x, set_x) 就可以按照屬性的方式訪問。或者訪問 set_x() 和 get_x() 方法。不過這樣違背了 Python 的一個哲學(philosophy):應該始終只有一種優先的解決方案,能夠很明顯的處理它

即便使用這種方法能夠解決問題,我們應該使用裝飾器 @property。因為這樣更 Pythonic。


分享到:


相關文章: