Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overloading + to support tuples

I'd like to be able to write something like this in python:

a = (1, 2)
b = (3, 4)
c = a + b # c would be (4, 6)
d = 3 * b # d would be (9, 12)

I realize that you can overload operators to work with custom classes, but is there a way to overload operators to work with pairs?

Of course, such solutions as

c = tuple([x+y for x, y in zip(a, b)])

do work, but, let aside performance, they aren't quite as pretty as overloading the + operator.

One can of course define add and mul functions such as

def add((x1, y1), (x2, y2)):
    return (x1 + x2, y1 + y2)

def mul(a, (x, y)):
    return (a * x, a * y)

but still being able to write q * b + r instead of add(times(q, b), r) would be nicer.

Ideas?

EDIT: On a side note, I realize that since + currently maps to tuple concatenation, it might be unwise to redefine it, even if it's possible. The question still holds for - for example =)

like image 419
Clément Avatar asked Apr 27 '11 09:04

Clément


People also ask

What is overloading in Python?

Overloading is the ability of a function or an operator to behave in different ways based on the parameters that are passed to the function, or the operands that the operator acts on. Some of the advantages of using overload are: Overloading a method fosters reusability.

Can you overload all operators in Python?

Python does not limit operator overloading to arithmetic operators only. We can overload comparison operators as well.

Which function overloads the >> operator in Python?

In Python, overloading is achieved by overriding the method which is specifically for that operator, in the user-defined class. For example, __add__(self, x) is a method reserved for overloading + operator, and __eq__(self, x) is for overloading == .

How do you overload a Len operator in Python?

Overloading Built-in Functions Consider the len() built-in function which returns the number of objects in a sequence or collection. To use it with our custom-made object type, we need to implement overloading. To overload len(), we need to extend the functionality of __len__ method in a class structure.


2 Answers

In contrast to Ruby, you can't change the behaviour of built-in types in Python. All you can do is create a new type derived from a built-in type. Literals will still create the built-in type, though.

Probably the best you can get is

class T(tuple):
    def __add__(self, other):
        return T(x + y for x, y in zip(self, other))
    def __rmul__(self, other):
        return T(other * x for x in self)
a = T((1, 2))
b = T((3, 4))
c = a + b # c would be (4, 6)
d = 3 * b # d would be (9, 12)
like image 95
Sven Marnach Avatar answered Sep 27 '22 21:09

Sven Marnach


You can inherit a class from tuple and overload its __add__ method. Here's a very simplistic example:

class mytuple(tuple):
    def __add__(self, other):
        assert len(self) == len(other)
        return tuple([x + y for x, y in zip(self, other)])

mt = mytuple((5, 6))
print mt + (2, 3)  # prints (7, 9)

I wouldn't recommend this approach though, because tuples weren't really designed for this purpose. If you want to perform numeric computations, just use numpy.

like image 28
Eli Bendersky Avatar answered Sep 27 '22 23:09

Eli Bendersky