【发布时间】:2015-01-08 18:52:54
【问题描述】:
我正在尝试找出一种方法,让属性的属性的设置器触发顶级类的某些操作。
作为一个虚拟示例,假设我的顶级课程是Segment。如果我将其端点的坐标直接存储为对象x0、y0、x1 和y1 的属性,并让每个对象的设置器触发所选操作,那么一切都很好。
但是如果我想将它们分成两个Point成员作为属性p0和p1,每个属性都有x和y,每当修改其中一个坐标时,没有明显的方法告诉Segment 做某事。这就是我希望能够做到的:
>>> segment = Segment(Point(0, 0), Point(3, 3))
>>> segment.p0
Point(0, 0)
>>> segment.p0.x
0
>>> segment.p1.y = 4
Length of segment changed to 5.0! # This can only be printed by segment, not p1!
问题是segment.p1.y = 4这行首先在segment实例上调用p1的getter,然后在上一个调用的返回上调用y的setter,此时不简单让segment 实例知道已进行更改的方式。
我现在能想到的最好的事情是这样的:
class Point(object):
def __init__(self, x, y, parent=None, name=None):
self.parent, self.name = parent, name
self._x, self._y = x, y
@property
def x(self):
return self._x
@x.setter
def x(self, value):
self._x = value
if parent is not None:
setattr(self.parent, self.name, self)
# Similar code for y goes here...
class Segment(object):
def __init__(self, p0, p1):
self.p0, self.p1 = p0, p1
@property
def p0(self):
return self._p0
@p0.setter
def p0(self, point):
self._p0 = point
self.p0.parent = self
self.p0.name = 'p0'
if not self._silent:
self.do_something() # This would print the length in the above example
# Similar code for p1 goes here...
虽然这可以满足我的要求,但我不太喜欢手动将该链接添加回父级,也不喜欢制作大量 Point 对象的冗余副本,或者冒险如果执行以下操作会出现有趣的错误:
p0, p1, p2 = Point(0, 0), Point(1, 1), Point(2, 2)
seg0 = Segment(p0, p1)
seg1 = Segment(p0, p2)
# The following line changes the value on both seg0 and seg1, but triggers
# the do_something call on seg1 only!
seg0.p0.x = 6
有现成的食谱吗?任何人都可以想出更好的方法吗?
【问题讨论】:
标签: python properties