Python 高手编程系列四百二十八:property

property 提供了一个内置的描述符类型,它知道如何将一个属性链接到一组方法上。
property 接受 4 个可选参数:fget、fset、fdel 和 doc。最后一个参数可以用来定义
一个链接到属性的 docstring,就像是一个方法一样。下面是一个 Rectangle 类的例子,
其控制方法有两种,一种是直接访问保存两个顶点的属性,另一种是利用 width 和
height。这两个 property,如下所示:
class Rectangle:
def init(self, x1, y1, x2, y2):
self.x1, self.y1 = x1, y1
self.x2, self.y2 = x2, y2
def _width_get(self):
return self.x2 - self.x1
def _width_set(self, value):
self.x2 = self.x1 + value
def _height_get(self):
return self.y2 - self.y1
def _height_set(self, value):
self.y2 = self.y1 + value
width = property(
_width_get, _width_set,
doc=“rectangle width measured from left”
)
height = property(
_height_get, _height_set,
doc=“rectangle height measured from top”
)
def repr(self):
return “{}({}, {}, {}, {})”.format(
self.class.name,
self.x1, self.y1, self.x2, self.y2
)
在交互式会话中,使用上述定义的 property 的示例如下:

rectangle = Rectangle(10, 10, 25, 34)
rectangle.width, rectangle.height
(15, 24)
rectangle.width = 100
rectangle
Rectangle(10, 10, 110, 34)
rectangle.height = 100
rectangle
Rectangle(10, 10, 110, 110)
help(Rectangle)
Help on class Rectangle in module chapter3:
class Rectangle(builtins.object)
| Methods defined here:
|
| __init __(self, x1, y1, x2, y2)
| Initialize self. See help(type(self)) for accurate signature.
|
| __repr __(self)
| Return repr(self).
|
| --------------------------------------------------------
| Data descriptors defined here:
| (…)
|
| height
| rectangle height measured from top
|
| width
| rectangle width measured from left
property 简化了描述符的编写,但在使用类的继承时必须小心处理。所创建的属性
是利用当前类的方法实时创建,不会使用派生类中覆写的方法。
例如,下面的例子将无法覆写父类(Rectangle)widthproperty 的fget 方法的实现:
class MetricRectangle(Rectangle):
… def _ width _get(self):
… return “{} meters”.format(self.x2 - self.x1)

Rectangle(0, 0, 100, 100).width
100
为了解决这一问题,只需要在派生类中覆写整个 property,如下所示:
class MetricRectangle(Rectangle):
… def _ width get(self):
… return “{} meters”.format(self.x2 - self.x1)
… width = property(
width _get, Rectangle.width.fset)

MetricRectangle(0, 0, 100, 100).width
‘100 meters’
不幸的是,上面的代码有一些可维护性的问题。如果开发人员决定要更改父类,但却
忘记修改 property 调用的话,就会出现问题。这就是为什么不建议仅覆写 property
的部分行为。如果需要修改property的工作方式,推荐在派生类中覆写所有的property
方法,而不是依赖父类的实现。在大多数情况下,这是唯一的选择,因为如果修改了
property 的 setter 行为的话,通常意味着也需要修改 getter 的行为。
基于上述原因,创建 property 的最佳语法是使用 property 作为装饰器。这会减少
类内部方法签名的数量,并提高代码的可读性和可维护性,如下所示:
class Rectangle:
def init(self, x1, y1, x2, y2):
self.x1, self.y1 = x1, y1
self.x2, self.y2 = x2, y2
@property
def width(self):
“”“rectangle height measured from top”“”
return self.x2 - self.x1
@width.setter
def width(self, value):
self.x2 = self.x1 + value
@property
def height(self):
“”“rectangle height measured from top”“”
return self.y2 - self.y1
@height.setter
def height(self, value):
self.y2 = self.y1 + value

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值