首页 > 解决方案 > How to implement Integer+MyObject()?

问题描述

Asking just out of curiocity. I've been playing around with python, and noticed this behaviour:

  1. (2).__add__(2) results in 4, which is totally expected;
  2. (2).__add__('a') results in NotImplemented - nothing weird yet;
  3. 'a'.__add__(2) produces an exception.

But, when trying to create my own class like so:

class Integer:
    def __init__(self, d):
        self.val = d
    def __add__(self, i):
        return self.val+int(i)
    def __iadd__(self, i):
        self.val += int(i)
        return self
    def __int__(self):
        return self.val

and comparing it to decimal.Decimal, some weird stuff happens. They behave similarly in this case:

import decimal

a = Integer(2)
a += 2
print(int(a+2))

d = decimal.Decimal(2)
d += 2
print(int(d+2))

However, this is not as similar: 2+d works normally while 2+a throws an exception:

Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    2+a
TypeError: unsupported operand type(s) for +: 'int' and 'Integer'

even though (2).__add__(a) and (2).__add__(d) both produce NotImplemented and a.__add__(2) and d.__add__(2) work normally. What exactly is happening with decimal.Decimal and how can I make this happen with my class?

标签: pythonpython-3.x

解决方案


Implement __radd__ too:

class Integer:
    def __init__(self, d):
        self.val = d

    def __add__(self, i):
        return self.val + int(i)

    def __radd__(self, i):
        return self.__add__(i)  # might be different if operation is not commutative

    def __iadd__(self, i):
        self.val += int(i)
        return self

    def __int__(self):
        return self.val


x = Integer(5) + 5
y = 5 + Integer(5)

推荐阅读