What is the specific code, in order, being executed when I ask for something like
>>> 1 <= 3 >= 2
True
If both have equal pr
I'm not totally sure what you're looking for, but a quick disassembly shows that a < b < c
is not compiled to the same bytecode as a < b and b < c
>>> import dis
>>>
>>> def f(a, b, c):
... return a < b < c
...
>>> dis.dis(f)
2 0 LOAD_FAST 0 (a)
3 LOAD_FAST 1 (b)
6 DUP_TOP
7 ROT_THREE
8 COMPARE_OP 0 (<)
11 JUMP_IF_FALSE_OR_POP 21
14 LOAD_FAST 2 (c)
17 COMPARE_OP 0 (<)
20 RETURN_VALUE
>> 21 ROT_TWO
22 POP_TOP
23 RETURN_VALUE
>>>
>>> def f(a, b, c):
... return a < b and b < c
...
>>> dis.dis(f)
2 0 LOAD_FAST 0 (a)
3 LOAD_FAST 1 (b)
6 COMPARE_OP 0 (<)
9 JUMP_IF_FALSE_OR_POP 21
12 LOAD_FAST 1 (b)
15 LOAD_FAST 2 (c)
18 COMPARE_OP 0 (<)
>> 21 RETURN_VALUE
Edit 1: Digging further, I think this is something weird or wrong with numpy. Consider this example code, I think it works as you would expect.
class Object(object):
def __init__(self, values):
self.values = values
def __lt__(self, other):
return [x < other for x in self.values]
def __gt__(self, other):
return [x > other for x in self.values]
x = Object([1, 2, 3])
print x < 5 # [True, True, True]
print x > 5 # [False, False, False]
print 0 < x < 5 # [True, True, True]
Edit 2: Actually this doesn't work "properly"...
print 1 < x # [False, True, True]
print x < 3 # [True, True, False]
print 1 < x < 3 # [True, True, False]
I think it's comparing boolean values to numbers in the second comparison of 1 < x < 3
.
Edit 3: I don't like the idea of returning non-boolean values from the gt, lt, gte, lte special methods, but it's actually not restricted according to the Python documentation.
http://docs.python.org/reference/datamodel.html#object.lt
By convention, False and True are returned for a successful comparison. However, these methods can return any value...
but the real question is how this gets implemented in code.
Do you mean how the interpreter transforms it, or what? You already said
a (logical operator) b (logical operator) c
--> (a logical operator b) and (b logical operator c)
so I'm not sure what you're asking here
OK, I figured it out: no, you cannot override the expansion from a < b < c
into (a < b) and (b < c)
IIUC.
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.
It depends which of a
, b
and c
in the expression a < b < c
are instances of your own class. Implementing your __lt__
and __gt__
and methods gets some of the way, but the documentation points out that:
There are no swapped-argument versions of these methods (to be used when the left argument does not support the operation but the right argument does)
So, if you want Int < MyClass < Int
, you're out of luck. You need, at a minimum, MyClass < MyClass < Something
(so an instance of your class is on the LHS of each comparison in the expanded expression).
Both have the same precedence, but are evaluated from left-to-right according to the documentation. An expression of the form a <= b <= c
gets expanded to a <= b and b <= c
.