码迷,mamicode.com
首页 > 编程语言 > 详细

Python @property

时间:2017-09-26 14:55:15      阅读:243      评论:0      收藏:0      [点我收藏+]

标签:log   iter   pow   imp   渐变   为我   set   只读   ack   

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: cant set attribute
>>> v1.y = 5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: cant 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

标签:log   iter   pow   imp   渐变   为我   set   只读   ack   

原文地址:http://www.cnblogs.com/z-joshua/p/7596500.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!