Damian Vu
Damian Vu

Reputation: 409

How do you support mixed arithmetic with a user defined class in python?

I'm curious as to how to support mixed arithmetic using a user-defined class in python. The docs state

Python fully supports mixed arithmetic: when a binary arithmetic operator has operands of different numeric types, the operand with the “narrower” type is widened to that of the other, where integer is narrower than floating point, which is narrower than complex.

The behavior I am trying to recreate can be seen with numpy

import numpy as np

a = np.array([1,2,3])

a + 5
Out[3]: array([6, 7, 8])

5 + a
Out[4]: array([6, 7, 8])

If I try to do this with a user defined class, I get something like this

from decimal import Decimal


class MyType:
    def __init__(self, value):
        self.value = Decimal(str(value))
    def __repr__(self):
        return f'<MyType {self.value}>'

    def __add__(self, other):
        if not isinstance(other, MyType):
            other = MyType(other)
        return MyType(self.value + other.value)

Then attempting to do something similar gives an error when the first addition argument is a float instead of my class.

a = MyType(.1)

a + 5
Out[14]: <MyType 5.1>

5 + a
Traceback (most recent call last):

  File "<ipython-input-15-35e25b55bb62>", line 1, in <module>
    5 + a

TypeError: unsupported operand type(s) for +: 'int' and 'MyType'

Upvotes: 1

Views: 377

Answers (2)

Amir
Amir

Reputation: 2041

In python you can define both __add__ and __radd__

So the easiest thing in your case to do is to add __radd__ = __add__

from decimal import Decimal

class MyType:
    def __init__(self, value):
        self.value = Decimal(str(value))

    def __repr__(self):
        return f'<MyType {self.value}>'

    def __add__(self, other):
        if not isinstance(other, MyType):
            other = MyType(other)
        return MyType(self.value + other.value) 
    
    __radd__ = __add__

Upvotes: 1

Daniel A R F
Daniel A R F

Reputation: 121

Seems something like link.

from decimal import Decimal

class MyType:
    def __init__(self, value):
        self.value = Decimal(str(value))
    def __repr__(self):
        return f'<MyType {self.value}>'
    def __add__(self, other):
        if not isinstance(other, MyType):
            other = MyType(other)
        return MyType(self.value + other.value)
    def __radd__(self, other):
        if not isinstance(other, MyType):
            other = MyType(other)
        return MyType(self.value + other.value)

Upvotes: 0

Related Questions