Overloading + to support tuples - python

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.

Related

Is there any way to perform this type of recursion in C++ or python?

Let us say I have a function called my_func(a,b,s,t). Suppose, I want a and b to be passed by value, but I want s and t to be passed by reference. As in, I want to some how pass in let us say (4,5,s',t'). The function performs computations by calling my_func(a/2,b/2,s/2,t/2). The thing is, there is a base case at the "bottom" of the recursion that gives concrete values to s and t.
Let me give a mini example:
def e_euclid(a,b,s,t):
if (a == b):
s = 4
t = -3
return a
if (a%2 == 0 and b%2 == 0):
if (s%2 == 0 and t%2 == 0):
return 2*e_euclid(a/2,b/2,s/2,t/2)
else:
return 2*e_euclid(a/2,b/2,(s+b)/2,(t-a)/2)
...
So, I would call this function as e_euclid(a,b, something, something) but then I would have to supply concrete values for s and t. Can you guys kind of see what I'm trying to do here?
Doing recursion where I return (s,t) would lead to a tough computation that I don't wish to perform, so I would like to do it this way.
Your code seems broken, already that base case (?) with a == b and s = 4 and t = -3 doesn't make sense. But see this C++ implementation and my Python translation using single-element lists instead of C++'s references:
def gcd(a, b, x=[None], y=[None]):
if b == 0:
x[0] = 1
y[0] = 0
return a
x1, y1 = [None], [None]
d = gcd(b, a % b, x1, y1)
x[0] = y1[0]
y[0] = x1[0] - y1[0] * (a // b)
return d
a, b = 123, 321
x, y = [None], [None]
print(gcd(a, b, x, y), x, y, a*x[0] + b*y[0])
Output (Try it online!):
3 [47] [-18] 3
I think you're trying to use the binary version of the algorithm, that should be doable the same way.

From Haskell to functional Python

I want to translate some Haskell code into Python.
The Haskell classes/instances look like:
{-# LANGUAGE MultiParamTypeClasses #-}
module MyModule where
class Example a b where
doSomething :: a -> b -> Bool
doSomethingElse :: a -> b -> Int
instance Example Int Int where
doSomething a b = (a + b * 2) > 5
doSomethingElse a b = a - b * 4
Is there a way in Python to approximate the Haskell class/instance construct?
What is the least offensive way to translate this into Python?
This doesn't really have an analogue in Python, but you can fake it:
def int_int_doSomething(a, b):
return (a + b * 2) > 5
def int_int_doSomethingElse(a, b):
return a - b * 4
Example = {}
Example[(int, int)] = (int_int_doSomething, int_int_doSomethingElse)
def doSomething(a, b):
types = type(a), type(b)
return Example[types][0](a, b)
def doSomethingElse(a, b):
types = type(a), type(b)
return Example[types][1](a, b)
All you have to do is add new values to Example for each type combination you want to have. You could even throw in some extra error handling in doSomething and doSomethingElse, or some other methods to make it easier. Another way would be to make an object that keeps track of all of these and lets you add new types to the map in a more managed way, but it's just more bookkeeping on top of what I've already shown.
Keep in mind that this is essentially how Haskell does it, too, except the checks are performed at compile time. Typeclasses are really nothing more than a dictionary lookup on the type to pick the appropriate functions to insert into the computation. Haskell just does this automatically for you at compile time instead of you having to manage it yourself like you do in Python.
To add that bookkeeping, you could do something like the following, keeping it in its own module and then it'll only (by default) export the symbols in __all__. This keeps things looking more like the Haskell version:
class _Example(object):
def __init__(self, doSomething, doSomethingElse):
self.doSomething = doSomething
self.doSomethingElse = doSomethingElse
ExampleStore = {}
def register(type1, type2, instance):
ExampleStore[(type1, type2)] = instance
def doSomething(a, b):
types = type(a), type(b)
return ExampleStore[types].doSomething(a, b)
def doSomethingElse(a, b):
types = type(a), type(b)
return ExampleStore[types].doSomethingElse(a, b)
def Example(type1, type2, doSomething, doSomethingElse):
register(type1, type2, _Example(doSomething, doSomethingElse))
__all__ = [
'doSomethingElse',
'doSomethingElse',
'Example'
]
Then you can make instances like
Example(int, int,
doSomething=lambda a, b: (a + b * 2) > 5,
doSomethingElse=lambda a, b: a - b * 4
)
Which looks almost like Haskell.
You don't have parametric types in Python, as it's dynamically typed. Also the distinction between classes and instances is clear in Python, but as classes are themselves "live objects", the distinction of usage might be a little bit blurred sometimes...
For your case, a classical implementation might go as:
#you don't really need this base class, it's just for documenting purposes
class Example:
def doSomething(self, a, b):
raise "Not Implemented"
def doSomethingElse(self, a, b):
raise "Not Implemented"
class ConcreteClass(Example):
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def doSomething(self, a, b):
return (a + b * self.x) > self.y
def doSomethingElse(self, a, b):
return a - b * self.z
instance = ConcreteClass((2, 5, 4)
but I personally dislike that convoluted style, so you might just go with something more lightweight, like:
from collections import namedtuple
Example = namedtuple('Example', 'doSomething doSomethingElse')
instance = Example((lambda a, b: (a + b * 2) > 5),
(lambda a, b: a - b *4 ))
And of course, rely on duck typing and usually "let it crash". The lack of type safety should be made up with extensive unit testing.

How to use a custom function in max(x, key=custom_function) function?

I have a custom data type, say: mytime, which represent hours and minutes, such as 29:45, it is 29 hours and 45 minutes.
I want to use max built-in function to find the item in a list of lists, whose sum of its elements is the greatest, where all lists contain values of mytime type.
x = [[a, b], [c, d]]
a,b,c,d are of mytime type.
max(x, key=sum)
won't work here, because a,b,c,d, are not integers.
If I type a + b at python command line, I get the sum of these two time values, result is of mytime type, without any errors.
How do I use max function here?
Let's say your class looks like this:
class mytime(object):
def __init__(self, h, m):
self.h = h
self.m = m
def __add__(self, other):
return mytime(self.h + other.h, self.m + other.m)
def __repr__(self):
return '%i:%i' % (self.h, self.m)
and you use it like this:
a = mytime(10, 10)
b = mytime(2, 22)
print a + b
and it will work as expect:
12:32
Problem:
What you want to do is:
l = [a, b]
print sum(l)
but it will fail:
TypeError: unsupported operand type(s) for +: 'int' and 'mytime'
The problem is that the sum function will start with 0 and will add up all values of the list. It will try to evaluate
0 + mytime(10, 10)
which will fail.
Solution:
The solution to your problem is implementing the __radd__ function, which represents "reverse add" and is called when the arguments can't be resolved in the "forward" direction. For example, x + y is evaluated as x.__add__(y) if possible, but if that doesn't exist then Python tries y.__radd__(x).
So you can add the following method to your class:
def __radd__(self, other):
return mytime(self.h, self.m)
and the sum function will work for you (in this implementation ignoring the other value, which is probably fine in your case).
You can write your own sum function:
def my_sum(item):
return sum(60 * e[0] + e[1] for e in item)
x = [[(2,0), (3,0)], [(9, 0), (4, 0)]]
print max(x, key=my_sum)
I have represented your mytime data structure as tuples (with hours and minutes) so you may need to adjust my_sum to your data structure. The only requirement is that the hours and minutes of a mytime can be filled in for e[0] and e[1] respectively.
The above code returns the greatest element (in this case [(9, 0), (4, 0)]).
Are you sure using a + b works? All sum does is repeatedly apply + to adjacent elements (it's the same as reduce(operator.add, sequence) with a special case to break on strings)... So if it does work - then max(x, key=sum) should just work -- as long as mydate supports comparison operators - eg __gt__, __eq__, __lt__
Example
You need to have __gt__ defined for max to work...
class mydate(object):
def __init__(self, num):
self.num = num
def __add__(self, other): # make sure sum works
return self.num + other.num
def __gt__(self, other): # make sure max can do > comparison
return self.num > other.num
def __repr__(self):
return 'date: {}'.format(self.num)
x = mydate(3)
y = mydate(5)
z = mydate(2)
print max([x,y,z], key=sum)

Python number-like class that remembers arithmetic operations?

I'm wondering if there exists a python module that would allow me to do something like this:
x = MagicNumber()
x.value = 3
y = 2 * (x + 2) ** 2 - 8
print y # 42
x.value = 2
print y # 24
So MagicNumber would implement all the special operator methods, and they would all return instances of MagicNumber, while keeping track of what operations are performed. Is there such a class?
EDIT: clarification
I want to use this in a module that should remember a lot of parameters of some arbitrary calculation that the user wishes to perform. So the user will set the parameters and then use them to produce his result. Then if he decides he'd like to alter a parameter, the change is reflected in his result immediately. So a very simplified usage session with only one parameter instance would look like:
p = MyParams()
p.distance = 13.4 # I use __getattr__ and __setattr__ such that
p.speed = 3.14 # __getattr__ returns MagicNumber instances
time = p.distance / p.speed
EDIT 2: more clarification
Okay, I'll do what I should have done from the start. I'll provide context.
You are an engineer and you're to produce a LaTeX document detailing the workings and properties of some prototype gadget. It is a task you'll do repeatedly for different prototypes. You write a small LaTeX python interface. For each prototype you create a python module that generates the requisite document. In it you type out the LaTeX code while calculating variables as they are needed, so that the calculations are in context. After a while you notice two problems:
The number of variables and parameters makes locals a mess and the variable names are hard to remember. You should group them into categories to keep track of them all.
You sometimes need to redo the same calculation, which is spread over the last couple of chapters and a dozen lines, with one or more parameters changed. You should find some way to avoid code duplication.
Out of this problem comes the original question.
Something like this?
import operator
MAKE_BINARY = lambda opfn : lambda self,other : BinaryOp(self, asMagicNumber(other), opfn)
MAKE_RBINARY = lambda opfn : lambda self,other : BinaryOp(asMagicNumber(other), self, opfn)
class MagicNumber(object):
__add__ = MAKE_BINARY(operator.add)
__sub__ = MAKE_BINARY(operator.sub)
__mul__ = MAKE_BINARY(operator.mul)
__radd__ = MAKE_RBINARY(operator.add)
__rsub__ = MAKE_RBINARY(operator.sub)
__rmul__ = MAKE_RBINARY(operator.mul)
# __div__ = MAKE_BINARY(operator.div)
# __rdiv__ = MAKE_RBINARY(operator.div)
__truediv__ = MAKE_BINARY(operator.truediv)
__rtruediv__ = MAKE_RBINARY(operator.truediv)
__floordiv__ = MAKE_BINARY(operator.floordiv)
__rfloordiv__ = MAKE_RBINARY(operator.floordiv)
def __neg__(self, other):
return UnaryOp(self, lambda x : -x)
#property
def value(self):
return self.eval()
class Constant(MagicNumber):
def __init__(self, value):
self.value_ = value
def eval(self):
return self.value_
class Parameter(Constant):
def __init__(self):
super(Parameter, self).__init__(0.0)
def setValue(self, v):
self.value_ = v
value = property(fset=setValue, fget=lambda self: self.value_)
class BinaryOp(MagicNumber):
def __init__(self, op1, op2, operation):
self.op1 = op1
self.op2 = op2
self.opn = operation
def eval(self):
return self.opn(self.op1.eval(), self.op2.eval())
class UnaryOp(MagicNumber):
def __init__(self, op1, operation):
self.op1 = op1
self.operation = operation
def eval(self):
return self.opn(self.op1.eval())
asMagicNumber = lambda x : x if isinstance(x, MagicNumber) else Constant(x)
And here it is in action:
x = Parameter()
# integer division
y = 2*x*x + 3*x - x//2
# or floating division
# y = 2*x*x + 3*x - x/2
x.value = 10
print(y.value)
# prints 225
x.value = 20
print(y.value)
# prints 850
# compute a series of x-y values for the function
print([(x.value, y.value) for x.value in range(5)])
# prints [(0, 0), (1, 5), (2, 13), (3, 26), (4, 42)]
You could give sympy, a computer algebra system written in Python, give a try.
E.g.
>>> from sympy import Symbol
>>> x = Symbol('x')
>>> y = 2 * (x + 2) ** 2 - 8
>>> y
2*(x + 2)**2 - 8
>>> y.subs(x,3)
42
>>> y.subs(x,2)
24
Isn't this called a function? This may sound like a simple answer, but I mean it sincerely.
def y(x):
return 2 * (x + 2) ** 2 - 8
Aren't you thinking in the wrong direction with this one?
To address the clarification:
class MyParams():
distance = 0.0
speed = 0.0
def __call__(self):
return self.distance / self.speed
p = MyParams()
p.distance = 13.4 # These are properties
p.speed = 3.14 # where __get__ returns MagicNumber instances
time = p() # 4.26
p.speed = 2.28
time = p() # 5.88
I guess I'm more in favor of this type of a solution, although I see the benefit in the sympy module. Preference, I guess.
>>> magic = lambda x: eval('2 * (x + 2) ** 2 - 8')
>>> magic(2)
24
>>> magic(3)
42
>>> magic = lambda x: eval('x ** 4')
>>> magic(2)
16
>>> magic(3)
81
I think the difficulty is in "how to keep operators priority" rather than implementing a class.
I suggest to look at a different notation (like Reverse Polish Notation) that may help in getting rid of priority issues...

Using Python tuples as vectors

I need to represent immutable vectors in Python ("vectors" as in linear algebra, not as in programming). The tuple seems like an obvious choice.
The trouble is when I need to implement things like addition and scalar multiplication. If a and b are vectors, and c is a number, the best I can think of is this:
tuple(map(lambda x,y: x + y, a, b)) # add vectors 'a' and 'b'
tuple(map(lambda x: x * c, a)) # multiply vector 'a' by scalar 'c'
which seems inelegant; there should be a clearer, simpler way to get this done -- not to mention avoiding the call to tuple, since map returns a list.
Is there a better option?
NumPy supports various algebraic operations with its arrays.
Immutable types are pretty rare in Python and third-party extensions thereof; the OP rightly claims "there are enough uses for linear algebra that it doesn't seem likely I have to roll my own" -- but all the existing types I know that do linear algebra are mutable! So, as the OP is adamant on immutability, there is nothing for it but the roll-your-own route.
Not that there's all that much rolling involved, e.g. if you specifically need 2-d vectors:
import math
class ImmutableVector(object):
__slots__ = ('_d',)
def __init__(self, x, y):
object.__setattr__(self, _d, (x, y))
def __setattr__(self, n, v):
raise ValueError("Can't alter instance of %s" % type(self))
#property
def x(self):
return self._d[0]
#property
def y(self):
return self._d[1]
def __eq__(self, other):
return self._d == other._d
def __ne__(self, other):
return self._d != other._d
def __hash__(self):
return hash(self._d)
def __add__(self, other):
return type(self)(self.x+other.x, self.y+other.y)
def __mul__(self, scalar):
return type(self)(self.x*scalar, self.y*scalar)
def __repr__(self):
return '%s(%s, %s)' % (type(self).__name__, self.x, self.y)
def __abs__(self):
return math.hypot(self.x, self.y)
I "threw in for free" a few extras such as .x and .y R/O properties, nice string representation, usability in sets or as keys in dicts (why else would one want immutability?-), low memory footprint, abs(v) to give v's vector-length -- I'm sure you can think of other "wouldn't-it-be-cool-if" methods and operators, depending on your application field, and they'll be just as easy. If you need other dimensionalities it won't be much harder, though a tad less readable since the .x, .y notation doesn't apply any more;-) (but I'd use genexps, not map).
By inheriting from tuple, you can make a nice Vector class pretty easily. Here's enough code to provide addition of vectors, and multiplication of a vector by a scalar. It gives you arbitrary length vectors, and can work with complex numbers, ints, or floats.
class Vector(tuple):
def __add__(self, a):
# TODO: check lengths are compatable.
return Vector(x + y for x, y in zip(self, a))
def __mul__(self, c):
return Vector(x * c for x in self)
def __rmul__(self, c):
return Vector(c * x for x in self)
a = Vector((1, 2, 3))
b = Vector((2, 3, 4))
print a + b
print 3 * a
print a * 3
Although using a library like NumPy seems to be the resolution for the OP, I think there is still some value in a simple solution which does not require additional libraries and which you can stay immutable, with iterables.
Using the itertools and operators modules:
imap(add, a, b) # returns iterable to sum of a and b vectors
This implementation is simple. It does not use lambda neither any list-tuple conversion as it is iterator based.
from itertools import imap
from operator import add
vec1 = (1, 2, 3)
vec2 = (10, 20, 30)
result = imap(add, vec1, vec2)
print(tuple(result))
Yields:
(11, 22, 33)
Why not create your own class, making use of 2 Cartesian point member variables? (sorry if the syntax is a little off, my python is rusty)
class point:
def __init__(self,x,y):
self.x=x
self.y=y
#etc
def add(self,p):
return point(self.x + p.x, self.y + p.y)
class vector:
def __init__(self,a,b):
self.pointA=a
self.pointB=b
#etc
def add(self,v):
return vector(self.pointA + v.pointA, self.pointB + v.pointB)
For occasional use, a Python 3 solution without repeating lambdas is possible via using the standard operator package:
from operator import add, mul
a = (1, 2, 3)
b = (4, 5, 6)
print(tuple(map(add, a , b)))
print(tuple(map(mul, a , b)))
which prints:
(5, 7, 9)
(4, 10, 18)
For serious linear algebra computations using numpy vectors is the canonical solution:
import numpy as np
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(a+b)
print(a*b)
which prints:
[5 7 9]
[ 4 10 18]
Since pretty much all of the sequence manipulation functions return lists, that's pretty much what you're going to have to do.

Categories