我想了解__add__
的工作原理:
class MyNum:
def __init__(self,num):
self.num=num
def __add__(self,other):
return MyNum(self.num+other.num)
def __str__(self):
return str(self.num)
如果我把它们放在一个列表中
d=[MyNum(i) for i in range(10)]
这是有效的
t=MyNum(0)
for n in d:
t=t+n
print t
但这不是:
print sum(d)
TypeError: unsupported operand type(s) for +: 'int' and 'instance'
我做错了什么?如何才能使 sum()起作用?
更新
我的问题是如何在支持__add__
的对象列表中使用总和,需要尽可能保持通用。
答案 0 :(得分:81)
您还需要定义__radd__
以使其生效。
__radd__
反向添加。当Python尝试评估x + y
时,它首先尝试调用x.__add__(y)
。如果此操作失败,则会回退到y.__radd__(x)
。
这允许您通过仅触摸一个类来覆盖添加。例如,考虑Python如何评估0 + x
。尝试拨打0.__add__(x)
,但int
对您的班级一无所知。您无法更改__add__
中的int
方法,因此需要__radd__
。我想这是一种依赖倒置的形式。
正如Steven所指出的那样,sum
在适当的位置运行,但从0开始。所以第一次添加是唯一需要使用__radd__
的。作为一个很好的练习,你可以检查是否是这种情况!
答案 1 :(得分:16)
>>> help(sum)
Help on built-in function sum in module __builtin__:
sum(...)
sum(sequence[, start]) -> value
Returns the sum of a sequence of numbers (NOT strings) plus the value
of parameter 'start' (which defaults to 0). When the sequence is
empty, returns start.
换句话说,提供一个起始值:
sum(d, MyNum(0))
从以下评论粘贴的编辑:
sum
使用整数零的默认起始值。您编写的MyNum
类不知道如何将自身添加到整数。要解决这个问题,您有两种选择。您可以为sum
提供与您的类型相同的类型的起始值,也可以实现__radd__
,在添加不同类型的值时Python调用(例如当将d
中的第一个值添加到默认起始值零时。
答案 2 :(得分:0)
class MyNum:
def __init__(self,num):
self.num=num
def __add__(self,other):
return self.num += other.num
def __str__(self):
return str(self.num)
one = MyNum(1)
two = MyNum(2)
one + two
print(two.num)
答案 3 :(得分:0)
另一个选项是reduce(Python 3.x中的functools.reduce)。
from functools import reduce
from operators import add
d=[MyNum(i) for i in range(10)]
my_sum = reduce(add,d)
答案 4 :(得分:0)
我反对使用起始点继续sum(),下面暴露的循环孔,
In [51]: x = sum(d, MyNum(2))
In [52]: x.num
Out[52]: 47
想知道为什么你在期待的时候得到47分 ...从MyNum()的第2个开始,先离开并将它们添加到结尾,所以预期结果= 44(总和(范围(2,10))
这里的事实是,2不是作为起始对象/位置保留,而是被视为对结果的补充
总和(范围(10))+ 2
哎呀,链接破了!!!!!!使用 radd
下面是正确的代码。另请注意以下
只有在+右侧的对象是您的类实例时,Python才会调用__radd__ 例如:2 + obj1
#!/usr/bin/env python
class MyNum:
def __init__(self,num):
self.num=num
def __add__(self,other):
return MyNum(self.num+other.num)
def __radd__(self,other):
return MyNum(self.num+other)
def __str__(self):
return str(self.num)
d=[MyNum(i) for i in range(10)]
print sum(d) ## Prints 45
d=[MyNum(i) for i in range(2, 10)]
print sum(d) ## Prints 44
print sum(d,MyNum(2)) ## Prints 46 - adding 2 to the last value (44+2)