Fluent 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: 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的更多相关文章
- 「Fluent Python」今年最佳技术书籍
Fluent Python 读书手记 Python数据模型:特殊方法用来给整个语言模型特殊使用,一致性体现.如:__len__, __getitem__ AOP: zope.inteface 列表推导 ...
- python property详解
Python中有一个被称为属性函数(property)的小概念,它可以做一些有用的事情.在这篇文章中,我们将看到如何能做以下几点: 将类方法转换为只读属性 重新实现一个属性的setter和getter ...
- python property
python property 在2.6版本中,添加了一种新的类成员函数的访问方式--property. 原型 class property([fget[, fset[, fdel[, doc]]]] ...
- python property装饰器
直接上代码: #!/usr/bin/python #encoding=utf-8 """ @property 可以将python定义的函数“当做”属性访问,从而提供更加友 ...
- Python @property 详解
本文讲解了 Python 的 property 特性,即一种符合 Python 哲学地设置 getter 和 setter 的方式. Python 有一个概念叫做 property,它能让你在 Pyt ...
- 学习笔记之Fluent Python
Fluent Python by Luciano Ramalho https://learning.oreilly.com/library/view/fluent-python/97814919462 ...
- Python property() 函数
Python property() 函数 Python 内置函数 描述 property() 函数的作用是在新式类中返回属性值. 语法 以下是 property() 方法的语法: class pro ...
- Fluent Python: memoryview
关于Python的memoryview内置类,搜索国内网站相关博客后发现对其解释都很简单, 我觉得学习一个新的知识点一般都要弄清楚两点: 1, 什么时候使用?(也就是能解决什么问题) 2,如何使用? ...
- Python深入学习之《Fluent Python》 Part 1
Python深入学习之<Fluent Python> Part 1 从上个周末开始看这本<流畅的蟒蛇>,技术是慢慢积累的,Python也是慢慢才能写得优雅(pythonic)的 ...
随机推荐
- CSS之元素
CSSS书写位置 内嵌式 <head> <style type = "text/css"> **** </style> </head> ...
- POJ 3528--Ultimate Weapon(三维凸包)
Ultimate Weapon Time Limit: 2000MS Memory Limit: 131072K Total Submissions: 2430 Accepted: 1173 ...
- ABAP术语-Sales Document
Sales Document 原文:http://www.cnblogs.com/qiangsheng/archive/2008/03/13/1103294.html Data base docume ...
- python2.7+PyQt4+eric6 界面开发环境配置
1.安装环境: python2.7 PyQt4-4.11.4-gpl-Py2.7-Qt4.8.7-x64.exe eric6-18.12.zip 2.安装步骤: 1.安装python2.7的过程略 2 ...
- Linux 学习第五天
一.重定向.管道符.通配符 1.重定向.管道符使用 重定向: 命令文件 管道符: 命令A:命令B (管道符 | 别称 “任意门”) 二.常用命令 1.ls /etc | wc -l (查看目录 ...
- 获取地图的信息到input里
在最近项目中,我接触了百度地图的API写法,对其中的代码有了一点兴趣,所以我在完成任务后,在办公室里学习了百度地图的相关引用,并申请了服务秘钥: E7PCho0sv3FdzmjC901ttP0HrS9 ...
- operator.attrgetter() 进行对象排序
## 使用operator.attrgetter() 进行对象排序 from operator import attrgetter class Student: def __init__(self, ...
- 实验吧web加了料的报错注入
知识点: SQL注入中用到的Concat函数详解 http://www.sohu.com/a/219966085_689961 http分割注入 直接根据提示,提交post请求的用户名和密码 结 ...
- [POJ3090]Visible Lattice Points(欧拉函数)
答案为3+2*∑φ(i),(i=2 to n) Code #include <cstdio> int T,n,A[1010]; void Init(){ for(int i=2;i< ...
- AtCoder Regular Contest 098 F.Donation
传送门 首先,对于一个点i,进入这个点前必须大于等于Ai,每个点必须捐赠Bi 那么我们可以在每个点最后一次经过的时候再捐赠,这样显然更优 现在我们假设每个点都是最后一次经过的时候捐赠.现在我们把捐赠的 ...