What is the specific code, in order, being executed when I ask for something like
>>> 1 <= 3 >= 2
True
If both have equal precedence and it's just the order of their evaluation, why does the second inequality function as (3 >= 2)
instead of (True >= 2)
Consider for example the difference between these
>>> (1 < 3) < 2
True
>>> 1 < 3 < 2
False
Is it just a pure syntactical short-cut hard-coded into Python to expand the second as the and
of the two statements?
Could I change this behavior for a class, such that a <= b <= c
gets expanded to something different? It's looking like the following is the case
a (logical operator) b (logical operator) c
--> (a logical operator b) and (b logical operator c)
but the real question is how this gets implemented in code.
I'm curious so that I can replicate this kind of __lt__
and __gt__
behavior in some of my own classes, but I am confused about how this is accomplished holding the middle argument constant.
Here's a specific example:
>>> import numpy as np
>>> tst = np.asarray([1,2,3,4,5,6])
>>> 3 <= tst
array([False, False, True, True, True, True], dtype=bool)
>>> 3 <= tst <= 5
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
/home/ely/<ipython-input-135-ac909818f2b1> in <module>()
----> 1 3 <= tst <= 5
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
It would be nice to override this so that it "just works" with arrays too, like this:
>>> np.logical_and(3 <= tst, tst <= 5)
array([False, False, True, True, True, False], dtype=bool)
Added for clarification
In the comments it is indicated that I did a poor job of explaining the question. Here's some clarifying remarks:
1) I am not looking for a simple explanation of the fact that the interpreter pops an and
in between the two chained inequalities. I already knew that and said so above.
2) For an analogy to what I want to do, consider the with
statement (link). The following:
with MyClass(some_obj) as foo:
do_stuff()
unpacks into
foo = MyClass(some_obj)
foo.__enter__()
try:
do_stuff()
finally:
foo.__exit__()
So by writing MyClass
appropriately, I can do many special things inside of the with
statement.
I am asking whether there is a similar code unpacking of the chained inequality by which I can intercept what it's doing and redirect it to use array-style logical operators instead just for the classes I care about.
I feel this is very clear from my question, especially the example, but hopefully this makes it more clear.