![](/img/trans.png)
[英]How to identify when an attribute's attribute is being set? - Although attribute is a list of objects
[英]How to recognize a attribute change when the attribute is a list of objects
矩形對象如何偵聽Points屬性x和y,如果它們發生變化,矩形對象將重新計算面積?
如果我使用setter和getter進行操作,則每次訪問area屬性時,都會重新計算面積。 如果計算非常昂貴(我在這里還要做更多的事情),那么這對我來說不是最佳解決方案。 是否可以聽取積分,僅在積分改變時重新計算面積?
我有一個叫做Rectangle的類和一個叫做Point的類:
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
class Rectangle(object):
def __init__(self, points=None):
self.points = [] if points is None else points
self.area = self.calc_area()
def calc_area(self):
return (self.points[0].x - self.points[1].x) * (self.points[0].y - self.points[1].y)
然后創建兩個點和一個包含兩個點的矩形:
# create the points:
points = list()
points.append(Point(0,0))
points.append(Point(1,1))
# create the rectangle:
rect = Rectangle(points)
print(rect.area)
現在,我更改第一點的坐標:
# change the points coordinates:
points[0].x = 0.5
points[0].y = 0.5
# Now the area should be recalculated.
print(rect.area)
您可以將area
聲明為property 。
class Rectangle(object):
def __init__(self, points=list()):
self.points = points
# self.area = self.calc_area() -- removed
@property
def area(self):
return = (self.points[0].x - self.points[1].x) * (self.points[0].y - self.points[1].y)
它將解決問題。
如果希望僅在值更改時才重新計算面積,則可以使用自定義標志並將其設置在屬性設置器上。
碼:
class Point(object):
def __init__(self, x, y):
self._x = x
self._y = y
self.updated = True
@property
def x(self):
return self._x
@x.setter
def x(self, value):
self.updated = True
self._x = value
@property
def y(self):
return self._y
@y.setter
def y(self, value):
self.updated = True
self._y = value
class Rectangle(object):
def __init__(self, points=None):
self.points = [] if points is None else points
self._area = 0
@property
def area(self):
if any(point.updated for point in self.points):
self._area = (self.points[0].x - self.points[1].x) * (self.points[0].y - self.points[1].y)
for point in self.points:
point.updated = False
print("recalculated") # delete it, it's just for test
return self._area
points = [Point(0, 0), Point(1, 1)]
rect = Rectangle(points)
print(rect.area)
print(rect.area)
points[0].x = 0.5
points[0].y = 0.5
print(rect.area)
輸出:
recalculated
1
1
recalculated
0.25
您可以:
rect.area
訪問rect.area
,只需在需要該區域時調用rect.calc_area()
謝謝@OlvinRoght,我認為您鏈接中的問題是實現此目的的最佳解決方案。 所以現在我實現了觀察者模式。 在這里,我可以將“矩形點”列表中的每個點綁定到更新函數。
class Point(object):
def __init__(self, x, y):
self._x = x
self._y = y
self._observers = []
@property
def x(self):
return self._x
@property
def y(self):
return self._y
@x.setter
def x(self, value):
self._x = value
for callback in self._observers:
print('announcing change')
callback()
@y.setter
def y(self, value):
self._y = value
for callback in self._observers:
print('announcing change')
callback()
def bind_to(self, callback):
print('bound')
self._observers.append(callback)
class Rectangle(object):
def __init__(self, points=None):
self.points = [] if points is None else points
self.area = []
for point in self.points:
point.bind_to(self.update_area)
self.area = (self.points[0].x - self.points[1].x) * (self.points[0].y - self.points[1].y)
def update_area(self):
print('updating area')
self.area = (self.points[0].x - self.points[1].x) * (self.points[0].y - self.points[1].y)
if __name__ == '__main__':
# create points:
points = list()
points.append(Point(0, 0))
points.append(Point(1, 1))
# create the rectangle:
rect = Rectangle(points)
print('Area = {}'.format(rect.area))
# change point coordinates
points[0].x = 0.5
points[0].y = 0.5
print('Area = {}'.format(rect.area))
# change point coordinates again:
points[0].x = 0.25
points[0].y = 0.25
print('Area = {}'.format(rect.area))
# just print the area; the area is not recalculated:
print('Area = {}'.format(rect.area))
輸出:
Area = 1
announcing change
updating area
announcing change
updating area
Area = 0.25
announcing change
updating area
announcing change
updating area
Area = 0.5625
Area = 0.5625
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.