Why does “not(True) in [False, True]” return False?

前端 未结 8 1220
清酒与你
清酒与你 2020-12-04 05:29

If I do this:

>>> False in [False, True]
True

That returns True. Simply because False is in the list.

相关标签:
8条回答
  • 2020-12-04 05:39

    Let's see it as a collection containment checking operation: [False, True] is a list containing some elements.

    The expression True in [False, True] returns True, as True is an element contained in the list.

    Therefore, not True in [False, True] gives the "boolean opposite", not result of the above expression (without any parentheses to preserve precedence, as in has greater precedence than not operator). Therefore, not True will result False.

    On the other hand, (not True) in [False, True], is equal to False in [False, True], which is True (False is contained in the list).

    0 讨论(0)
  • 2020-12-04 05:46

    Operator precedence. in binds more tightly than not, so your expression is equivalent to not((True) in [False, True]).

    0 讨论(0)
  • 2020-12-04 05:46

    It's all about operator precedence (in is stronger than not). But it can be easily corrected by adding parentheses at the right place:

    (not(True)) in [False, True]  # prints true
    

    writing:

    not(True) in [False, True]
    

    is the same like:

    not((True) in [False, True])
    

    which looks if True is in the list and returns the "not" of the result.

    0 讨论(0)
  • 2020-12-04 05:48

    not x in y is evaluated as x not in y

    You can see exactly what's happening by disassembling the code. The first case works as you expect:

    >>> x = lambda: False in [False, True]
    >>> dis.dis(x)
      1           0 LOAD_GLOBAL              0 (False)
                  3 LOAD_GLOBAL              0 (False)
                  6 LOAD_GLOBAL              1 (True)
                  9 BUILD_LIST               2
                 12 COMPARE_OP               6 (in)
                 15 RETURN_VALUE
    

    The second case, evaluates to True not in [False, True], which is False clearly:

    >>> x = lambda: not(True) in [False, True]
    >>> dis.dis(x)
      1           0 LOAD_GLOBAL              0 (True)
                  3 LOAD_GLOBAL              1 (False)
                  6 LOAD_GLOBAL              0 (True)
                  9 BUILD_LIST               2
                 12 COMPARE_OP               7 (not in)
                 15 RETURN_VALUE        
    >>> 
    

    What you wanted to express instead was (not(True)) in [False, True], which as expected is True, and you can see why:

    >>> x = lambda: (not(True)) in [False, True]
    >>> dis.dis(x)
      1           0 LOAD_GLOBAL              0 (True)
                  3 UNARY_NOT           
                  4 LOAD_GLOBAL              1 (False)
                  7 LOAD_GLOBAL              0 (True)
                 10 BUILD_LIST               2
                 13 COMPARE_OP               6 (in)
                 16 RETURN_VALUE        
    
    0 讨论(0)
  • 2020-12-04 05:49

    It is evaluating as not True in [False, True], which returns False because True is in [False, True]

    If you try

    >>>(not(True)) in [False, True]
    True
    

    You get the expected result.

    0 讨论(0)
  • 2020-12-04 05:51

    Alongside the other answers that mentioned the precedence of not is lower than in, actually your statement is equivalent to :

    not (True in [False, True])
    

    But note that if you don't separate your condition from the other ones, python will use 2 roles (precedence or chaining) in order to separate that, and in this case python used precedence. Also, note that if you want to separate a condition you need to put all the condition in parenthesis not just the object or value :

    (not True) in [False, True]
    

    But as mentioned, there is another modification by python on operators that is chaining:

    Based on python documentation :

    Note that comparisons, membership tests, and identity tests, all have the same precedence and have a left-to-right chaining feature as described in the Comparisons section.

    For example the result of following statement is False:

    >>> True == False in [False, True]
    False
    

    Because python will chain the statements like following :

    (True == False) and (False in [False, True])
    

    Which exactly is False and True that is False.

    You can assume that the central object will be shared between 2 operations and other objects (False in this case).

    And note that its also true for all Comparisons, including membership tests and identity tests operations which are following operands :

    in, not in, is, is not, <, <=, >, >=, !=, ==
    

    Example :

    >>> 1 in [1,2] == True
    False
    

    Another famous example is number range :

    7<x<20
    

    which is equal to :

    7<x and x<20   
    
    0 讨论(0)
提交回复
热议问题