I use Python to wrap a powerful library (from another language) which manipulates expressions and relations. For that matter, I extensively use overloading of operators and it works like a charm.
Now, I would need to define a max function that would apply on my expressions to generate a new expression intuitively representing the "max of all expressions in the iterable (these expressions being not yet evaluated)."
Since the built-in function max uses iterators and some kind of order relation implemented as __leq__, etc., (which I use for generating relations from two expressions) I end up getting nonsense when I apply the built-in max on a set of expression.
More specifically,
>>> max(e1, e2, e3)
e3
although I would love to raise some kind of exception saying "Please use my specific function I am pointing here that would generate the new expression you reasonably expect"
My bottom-line is that even if I have a different function implementing max for expressions:
- I don't want to leave this behaviour as is and let users think they are safe doing
max(e1, e2, e3). - I want
maxto work as usual with regular Python objects.
The only way-out of this issue I can think of would start by tricking the key option of max to raise an exception when it hits an object of a specific type:
def newkey(p):
if isinstance(p, Expression):
raise SyntaxError("Use function `foo` for computing `max`")
# fallback to regular behaviour I know nothing about yet
max(e1, e2, e3, key=newkey)
Now I cannot force users to specify the key option each time they call max. As a matter of fact, if I could, I would tell them to use a different max function anyway...
Can you see a way out of this? (or a better workaround)
__leq__correctly?__leq__returns an instance ofRelationwhich is not yet evaluated (as expressions are not yet evaluated) and is neitherTruenorFalse.__bool__onRelationso it will be evaluated. Or__nonzero__if using Python 2.max(e1, e2, e3)to implicitly evaluate the expressions. You could design for this behavior, then add alazy_maxfunction to your module to return aLazyMaxobject. That covers all of your bases.