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 =)
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)
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
.
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.
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|
.
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.
Write your own class and implement __mul__, __add__
etc.
You can use numpy.array
to get all you need.
来源:https://stackoverflow.com/questions/5802020/overloading-to-support-tuples