Python @property
阿新 • • 發佈:2017-09-26
temp iter com 解決 需要 想要 all most last
Fluent Python 9.6節講到hashable Class,
為了使Vector2d類可散列,有以下條件:
(1)實現__hash__方法
(2)實現__eq__方法
(3)讓Vector2d向量不可變
如何讓Vector2d類實例的向量只讀呢?可以使用property,如下所示:
class Vector2d: def __init__(self, x, y): self._x = x self.__y = y @property # The @property decorator marks the getter method of a property.def x(self): return self._x @property # The @property decorator marks the getter method of a property. def y(self): return self.__y def __hash__(self): return hash(self._x) ^ hash(self.__y) def __eq__(self, other): return hash(self) == hash(other)def __iter__(self): return (i for i in (self._x, self.__y))
我們在控制臺嘗試修改x或者y:
>>> import Example9_7 >>> v1 = Example9_7.Vector2d(3, 4) >>> v1.x 3 >>> v1.x = 4 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: can‘t set attribute >>> v1.y = 5 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: can‘t set attribute
這是我們想要的行為,但是為什麽加上@properly裝飾器後就變為只讀了呢?我們需要對property有更深入的了解。
An Example To Begin With:
在此之前,我們先來看看property的應用場景:
假設我們寫了一個關於溫度的類:
class Celsius: def __init__(self, temperature=0): self.temperature = temperature def get_fahrenheit(self): return self.temperature * 1.8 + 32
並且這個類漸漸變的很流行,被很多用戶所調用,有一天,一個用戶跑來建議說,溫度不應該低於絕對溫度-273攝氏度,他要求我們實現這個限制。
為了這樣實現用戶的要求,我們更新為v1.1:
class Celsius: def __init__(self, temperature=0): self.__temperature = temperature def get_fahrenheit(self): return self.__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
用戶的要求是實現了 可以這裏有個問題,用戶的代碼裏任然是這樣獲取溫度的:
c = Celsius(37)
c.temperature = 20
current_temperature = c.temperature
而且代碼裏有成百上千行如此的代碼,這些代碼不得不改為:
c.set_temperature(20)
c.get_temperature()
對於用戶來說這是很頭疼的問題,因為我們的修改不是backward compatible.
The Power of @property:
對於這個問題,更為Pythonic解決方式如下:
1 class Celsius: 2 def __init__(self, temperature=0): 3 self.__temperature = temperature 4 5 def get_fahrenheit(self): 6 return self.__temperature * 1.8 + 32 7 8 def get_temperature(self): 9 return self.__temperature 10 11 def set_temperature(self, value): 12 if value < -273: 13 raise ValueError("Temperature below -273 is not possible.") 14 self.__temperature = value 15 16 temprature = property(get_temperature, set_temperature)
這樣,用戶任然像以前一樣訪問temprature:
>>> c1 = property_demo.Celsius(10) >>> c1.temprature 10 >>> c1.temprature = 20 >>> c1.temprature 20
因此我們既實現了對termperature的限制,有保證了向後兼容
Digging Deeper into Property:
Python @property