Overloading + to support tuples

99封情书 提交于 2019-12-07 06:28:54

问题


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 =)


回答1:


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)



回答2:


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.




回答3:


You cannot modify types defined in C, so you would need to create all new types for this. Or you could just use NumPy, which already has types that support this.




回答4:


There is the famous infix operator hack that would allow you to do soemthing like this:

x = Infix(lambda a,b:tuple([x+y for x, y in zip(a, b)]))
y = Infix(lambda a,b:tuple([a*y for y in b]))

c = a |x| b # c would be (4, 6)
d = 3 |y| b # d would be (9, 12) 

That would hide the generator expressions and be applicable to tuples of all lengths, at the expense of "weird" pseudo-operators |x| and |y|.




回答5:


Using python complex numbers is definitely one way to do it, if not extremely pretty.

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

That saves the definition of an extra class.

Also, expanding on previous answers,

class T(tuple):
    def __add__((x, y), (x1, y1)):
        return T((x+x1, y+y1))
    def __rmul__((x, y), other):
        return T((other * x, other * y))

would improve performance, at the cost of restraining the implementation to pairs.




回答6:


Write your own class and implement __mul__, __add__ etc.




回答7:


You can use numpy.array to get all you need.



来源:https://stackoverflow.com/questions/5802020/overloading-to-support-tuples

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!