I'm asking for suggestions on how to get "close" to overloading the and
operator. A code example to hint at what I'm doing:
import operator
OP = { operator.ge: ">=", operator.le: "<=" }
class Expression(object):
def __init__(self, left, right, op):
self.left = left
self.right = right
self.op = op
def __le__(self, other):
return Expression(self, other, operator.le)
def __ge__(self, other):
return Expression(self, other, operator.ge)
def __str__(self):
return "(%s %s %s)" % (self.left, OP[self.op], self.right)
def __repr__(self):
return "<Expression: %s %s %s>" % (self.left, self.op, self.right)
class Variable(Expression):
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
def __repr__(self):
return "<Variable: %s>" % self.name
def _and(left, right):
return (left, right)
print 1 <= Variable("x") <= 3
print _and(1 <= Variable("x"), Variable("x") <= 3)
The above example prints:
(x <= 3)
(<Expression: x <built-in function ge> 1>, <Expression: x <built-in function le> 3>)
According to the Python docs an expression 1 <= a <= 2
translates to 1 <= a and a <= 2
, so I'm guessing that in my example 1 <= Variable("x")
evaluates to True
so the expression returns the value of Variable("x") <= 3
. I need a way to get both expressions (1 <= a
, and a <= 2
) separately, and preferably without writing out the middle expression twice (like I did with the _and function), since the middle expression could be quite complex and bothersome to have twice (I realize I could save it to a variable and use it, but this is also less readable). According to this SE post the and
operator can't be overloaded, so what I'm asking is whether this can be done, and then how, or if I have to resort to splitting the comparison in two (specifying the middle expression twice). Any suggestions in the right direction are appreciated! Thank you.
Possibly related:
Edit: So what I'm essentially doing is writing out constraints for a linear program, so relevant parts of my code currently look something like this:
model.add_constr(a <= b)
model.add_constr(b <= c)
# now i could alter add_constr to support either a tuple or two arguments enabling:
model.add_constr(a <= b, b <= c)
model.add_constr((a <= b, b <= c))
# but most pleasing would be if I could do
model.add_constr(a <= b <= c)
# that would return for example a two tuple that could be interpreted appropriately by
# add_constr()