覆盖__add__方法后出现TypeError

Ηλί*_*ίας 35 python

我试图了解它是如何__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)
Run Code Online (Sandbox Code Playgroud)

如果我把它们放在一个清单中

d=[MyNum(i) for i in range(10)]
Run Code Online (Sandbox Code Playgroud)

这很有效

t=MyNum(0)
for n in d:
    t=t+n
print t
Run Code Online (Sandbox Code Playgroud)

但这不是:

print sum(d)
TypeError: unsupported operand type(s) for +: 'int' and 'instance'
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?我怎样才能得到sum()

UPDATE

我的问题是如何在支持的对象列表上使用总和__add__,需要尽可能保持通用.

Dav*_*nan 83

您还需要定义__radd__以使其工作.

__radd__反向加.当Python试图评估x + y它时,首先尝试调用x.__add__(y).如果失败则会回落y.__radd__(x).

这允许您通过仅触摸一个类来覆盖添加.考虑一下Python必须如何评估0 + x.0.__add__(x)尝试打电话但int对你的班级一无所知.你不能很好地改变__add__方法int,因此需要__radd__.我想这是一种依赖倒置的形式.

正如史蒂文所指出的,sum操作就位,但从0开始.所以第一次添加是唯一需要使用的__radd__.作为一个很好的练习你可以检查是这样的!


Ste*_*ski 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.
Run Code Online (Sandbox Code Playgroud)

换句话说,提供一个起始值:

sum(d, MyNum(0))
Run Code Online (Sandbox Code Playgroud)

从以下评论中粘贴编辑:

sum使用整数零的默认起始值​​.你MyNum编写的类不知道如何将自己添加到整数.要解决这个问题,您有两种选择.您可以提供sum与您的类具有相同类型的起始值,或者您可以实现__radd__,在添加不同类型的值时(例如,将第一个值d添加到默认起始值​​零时),Python会调用这些值.

  • @Ηλίας:`sum`使用整数零的默认起始值​​.您编写的`MyNum`类不知道如何将自身添加到整数.要解决这个问题,您有两种选择.你可以为你的类的类型提供一个'sum`的起始值,或者你可以实现`__radd__`,Python在添加不同类型的值时调用(例如当添加`d`中的第一个值时到起始值为零). (3认同)