我想在Python中创建一个类,实现一个__add__
对象方法,它允许对同一个类的两个对象求和,让我们调用这个类Indicator
和这两个对象来对ind1
和ind2
求和,Indicator
对象只有一个属性elements
,它是一个整数值字典。
我的__add__
实现结合了两个对象的elements
属性,最终用同一个键对这些值求和。
from __future__ import annotations
import copy
class Indicator:
def __init__(self, elements={}):
self.elements = elements
def __add__(self, other: Indicator):
new = copy.deepcopy(self)
new.values = {k: self.elements.get(k, 0) + other.elements.get(k, 0) for k in set(self.elements) | set(other.elements)}
return new
ind1 = Indicator({1:1,2:2,3:3})
ind2 = Indicator({1:1,2:2})
new = ind1 + ind2
print('ind1: ',ind1.elements)
print('ind2: ',ind2.elements)
print(new.elements) # {1: 2, 2: 4, 3: 3}
我希望__add__
返回一个对象,其elements
属性随着求和中的一个或两个对象在代码流中的更新而更新。
例如,
ind1.elements[4] = 4
print(new.elements) # I would like this to be {1: 2, 2: 4, 3: 3, 4:4}
ind1.elements[1] = 3
print(new.elements) # I would like this to be {1: 4, 2: 4, 3: 3, 4:4}
我该怎么做呢?
- 编辑**
首先,感谢所有发表评论/回答的用户,根据评论和回答中给出的建议,我想出了以下解决方案,想法是添加两个列表作为Indicator
的属性:self.adds
和self.linked
。
- 列表
self.adds
收集求和的加数。当__add__
被调用时,它被填满。因此,在下面的例子中,ind1.adds is []
和ind2.adds is []
,因为这两个对象不是从求和中产生的。相反,new.adds is [ind1,ind2]
- 列表
self.linked
收集了所有在self
更新时需要更新的对象。在下面的例子中,ind1.linked is [new]
和ind2.linked is [new]
。
我对这个解决方案并不完全满意。例如,如果我们对三个对象求和,然后修改其中一个,它就无法工作。我可以尝试修复代码,但我想知道我是否在做一些非常规的事情。有什么想法吗?代码如下所示
from __future__ import annotations
import copy
class Indicator:
def __init__(self, elements=None):
if elements is None:
self._elements = {}
else:
self._elements = elements
self.adds = []
self.linked = []
@property
def elements(self):
return self._elements
@elements.setter
def elements(self, value):
self._elements = value
for i in range(len(self.linked)):
el = self.linked[i]
el.update()
def update(self):
summation = self.adds[0]
for obj in self.adds[1:]:
summation = summation.__add__(obj)
self._elements = summation.elements
def __add__(self, other: Indicator):
new = copy.deepcopy(self)
self.linked.append(new)
other.linked.append(new)
new.adds = [self, other]
new._elements = {k: self.elements.get(k, 0) + other.elements.get(k, 0) for k in
set(self.elements) | set(other.elements)}
return new
ind1 = Indicator({1: 1, 2: 2, 3: 3})
ind2 = Indicator({1: 1, 2: 2})
new = ind1 + ind2
print('ind1: ', ind1.elements)
print('ind2: ', ind2.elements)
print(new.elements) # {1: 2, 2: 4, 3: 3}
ind1.elements = {0: 0, 1: 3}
print('Updating ind1: ',new.elements == (ind1+ind2).elements)
ind2.elements = {0: 0, 7: 9}
print('Updating ind2: ',new.elements == (ind1+ind2).elements)
3条答案
按热度按时间wqsoz72f1#
一个非常粗略的想法如何可以做到这一点(有很多工作留给你):
图纸
bq9c1y662#
我将@MichaelButscher的建议和您的更新合并到一段代码中,添加了对象的名称,并将
print
保留在notify
中以供演示;注意,notify
中的diff
参数意味着它只对数值有效(但是,既然您实现了__add__
方法,那么这应该不是问题!)示例
pqwbnv8z3#
您的问题与此行有关:
当你真的只需要密钥时,你正在创建k:v对的集合。下面是一个可行的解决方案: