What is the operator precedence when writing a double inequality in Python (explicitly in the code, and how can this be overridden for arrays?)

后端 未结 3 806
悲哀的现实
悲哀的现实 2020-12-18 21:52

What is the specific code, in order, being executed when I ask for something like

>>> 1 <= 3 >= 2
True

If both have equal pr

相关标签:
3条回答
  • 2020-12-18 22:31

    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...

    0 讨论(0)
  • 2020-12-18 22:32

    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).

    0 讨论(0)
  • 2020-12-18 22:52

    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.

    0 讨论(0)
提交回复
热议问题