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之前,我们先来看看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的解决方式如下:

 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 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()是一个内建函数(Built-in function),它返回property 对象,函数原型是:

property(fget=None, fset=None, fdel=None, doc=None)
# fget is function to get value of the attribute, fset is function to set value of the attribute, fdel is function to delete the attribute and doc is a string (like a comment).
>>> property()
<property object at 0x7f50058bc5e8>

我们之前的示例可以分解为:

# make empty property
temperature = property()
# assign fget
temperature = temperature.getter(get_temperature)
# assign fset
temperature = temperature.setter(set_temperature)

我们也可以用装饰器来实现以上的功能:

class Celsius:
def __init__(self, temperature=0):
self.__temperature = temperature def get_fahrenheit(self):
return self.__temperature * 1.8 + 32 @property
def temperature(self):
return self.__temperature @temperature.setter
def temperature(self, value):
if value < -273:
raise ValueError("Temperature below -273 is not possible")
self.__temperature = value

装饰器版本是更为简单,推荐的方式。

Fluent Python: @property的更多相关文章

  1. 「Fluent Python」今年最佳技术书籍

    Fluent Python 读书手记 Python数据模型:特殊方法用来给整个语言模型特殊使用,一致性体现.如:__len__, __getitem__ AOP: zope.inteface 列表推导 ...

  2. python property详解

    Python中有一个被称为属性函数(property)的小概念,它可以做一些有用的事情.在这篇文章中,我们将看到如何能做以下几点: 将类方法转换为只读属性 重新实现一个属性的setter和getter ...

  3. python property

    python property 在2.6版本中,添加了一种新的类成员函数的访问方式--property. 原型 class property([fget[, fset[, fdel[, doc]]]] ...

  4. python property装饰器

    直接上代码: #!/usr/bin/python #encoding=utf-8 """ @property 可以将python定义的函数“当做”属性访问,从而提供更加友 ...

  5. Python @property 详解

    本文讲解了 Python 的 property 特性,即一种符合 Python 哲学地设置 getter 和 setter 的方式. Python 有一个概念叫做 property,它能让你在 Pyt ...

  6. 学习笔记之Fluent Python

    Fluent Python by Luciano Ramalho https://learning.oreilly.com/library/view/fluent-python/97814919462 ...

  7. Python property() 函数

    Python property() 函数  Python 内置函数 描述 property() 函数的作用是在新式类中返回属性值. 语法 以下是 property() 方法的语法: class pro ...

  8. Fluent Python: memoryview

    关于Python的memoryview内置类,搜索国内网站相关博客后发现对其解释都很简单, 我觉得学习一个新的知识点一般都要弄清楚两点: 1, 什么时候使用?(也就是能解决什么问题) 2,如何使用? ...

  9. Python深入学习之《Fluent Python》 Part 1

    Python深入学习之<Fluent Python> Part 1 从上个周末开始看这本<流畅的蟒蛇>,技术是慢慢积累的,Python也是慢慢才能写得优雅(pythonic)的 ...

随机推荐

  1. HDU 1411--校庆神秘建筑(欧拉四面体体积计算)

    校庆神秘建筑 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  2. wso2 ei 6.4.0安装笔记

    目的:将最新版(6.4.0)部署在linux服务器,与Api Manager部署在同一环境 环境: Centos 7.3 Jdk 8 Mysql 5.7 问题一: 将H2替换为Mysql5.7数据库时 ...

  3. 《黑客攻防技术宝典Web实战篇@第2版》读书笔记1:了解Web应用程序

    读书笔记第一部分对应原书的第一章,主要介绍了Web应用程序的发展,功能,安全状况. Web应用程序的发展历程 早期的万维网仅由Web站点构成,只是包含静态文档的信息库,随后人们发明了Web浏览器用来检 ...

  4. 10分钟搞定webpack打包

    入门前端这个职位近三年的时间了,但是脑子里的东西不多也不少,今天就从脑袋里把新版本的webpack打包过程拔出来给大家鲁一遍,就算帮助那些小白了,废话不多说,开始鲁起来,大家跟着我一起撸... 首先, ...

  5. 移动端网站通用模板 单位rem

    html <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8& ...

  6. Hadoop-Hive学习笔记(1)

    1. Hive什么 a.Hive是基于Hadoop的一个数据仓库工具(注意不是数据仓库),将结构化的数据文件映射成一张数据库表. b.Hive是SQL的解析引擎,可以把sql语句转换成MapReduc ...

  7. [OpenCV][关于OpenCV3.2.0+VS2015+Win10环境搭建]

    在VS2015上搭建OpenCV3.2.0+Win10 1.OpenCV3.2.0在VS2015上的配置 1).下载.解压OPENCV 登陆OpenCV官方网站下载相应版本的OpenCV-SDK 这里 ...

  8. linux驱动动态与静态加载

    在Linux中驱动的加载方式有动态加载和静态加载.动态加载,即驱动不添加到内核中,在内核启动完成后,仅在用到这一驱动时才会进行加载静态加载,驱动编译进内核中,随内核的启动而完成驱动的加载.添加字符驱动 ...

  9. .Net 面试题 汇总(五)

    1.简述javascript中的“=.==.===”的区别? =赋值 ==比较是否一般相等 "3"==3 //会做类型的隐式转换,true ===比较是否严格相等 "3& ...

  10. 理解C指针: 一个内存地址对应着一个值

    一个内存地址存着一个对应的值,这是比较容易理解的. 如果程序员必须清楚地知道某块内存存着什么内容和某个内容存在哪个内存地址里了,那他们的负担可想而知.    汇编语法对“一个内存地址存着一个对应的数” ...