Python @property

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python @property相关的知识,希望对你有一定的参考价值。

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的主要内容,如果未能解决你的问题,请参考以下文章

Xcode 快速开发 代码块

Xcode 快速开发 代码块 快捷键

代码片段

[原创]java WEB学习笔记61:Struts2学习之路--通用标签 property,uri,param,set,push,if-else,itertor,sort,date,a标签等(代码片段

solr分布式索引实战分片配置读取:工具类configUtil.java,读取配置代码片段,配置实例

Xcode自定义代码块