2

I would have expected it to either have parenthesis to the left or to the right.

But it seems to do something else!

>>> 12 in [12,13,14] == True
False
>>> (12 in [12,13,13]) == True
True
>>> 12 in ([12,13,14] == True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: argument of type 'bool' is not iterable
josinalvo
  • 1,366
  • 13
  • 26
  • 5
    you're evaluating whether the integer 12 is in a boolean object. not possible. – Teejay Bruno Feb 19 '21 at 17:33
  • 1
    Does this answer your question? [Python operator precedence](https://stackoverflow.com/questions/3328355/python-operator-precedence) – Péter Leéh Feb 19 '21 at 17:36
  • I admit I'm a little surprised about `12 in [12,13,14] == True` being False. If `in` comes before `==`, then I'd except the result to be True. If `in` comes after `==`, I'd expect it to be a syntax error. What's the difference between the first and second expressions? – Kirk Strauser Feb 19 '21 at 17:41
  • 2
    The first expression is `(12 in [12,13,14]) and ([12,13,14] == True)` and the second group is `False`. What make it even more interesting ist that `if [12,13,14]` evaluates to `True` – Francesco Montesano Feb 19 '21 at 17:42
  • @FrancescoMontesanon I can't see how the first expression would be `(12 in [12,13,14]) and ([12,13,14] == True)`. I'd think it would be identical to the second expression. – Kirk Strauser Feb 19 '21 at 17:47
  • @FrancescoMontesano yes, it is clear from the actual list with `None` in place of `print`. Which clearly shows the list is evaluated first. Thank you. – Epsi95 Feb 19 '21 at 17:51
  • @KirkStrauser: the [python documentation](https://docs.python.org/3/reference/expressions.html#comparisons) and @Epsi95 answer shows that this is what python does. When I rewrite the expression as above I get a `False` – Francesco Montesano Feb 19 '21 at 17:53
  • 1
    Does this answer your question? [Unexpected result from \`in\` operator - Python](https://stackoverflow.com/questions/45180899/unexpected-result-from-in-operator-python) – wjandrea Feb 19 '21 at 17:53
  • @PéterLeéh That's not an ideal duplicate cause it primarily talks about operators that *don't* chain. I suggested a more exact duplicate above. – wjandrea Feb 19 '21 at 17:53

2 Answers2

9

That the following expression evaluates to False may be surprising:

12 in [12,13,14] == True

Here's what's happening: the in and == operators have the same precedence, and they support left-to-right chaining (see the docs), so the expression is equivalent to

12 in [12,13,14] and [12,13,14] == True

Now and is less binding, and the left-hand side obviously evaluates to True. Now for the tricky part: a non-empty sequence, such as the [12, 13, 14] list evaluates to True, but it is not equal to True. It's a so-called "truthy" value. Truthy and Falsy values are not booleans (not instances of type bool), but they evaluate to either True or False.

So they right-hand side of the and comparison evaluates to False.

wjandrea
  • 28,235
  • 9
  • 60
  • 81
joao
  • 2,220
  • 2
  • 11
  • 15
  • But I am curious about truthy value thing. Since `[12,13,14] == True` here it will only be true if both are list and the list elements arr equal. How does the truthly value thing comes into picture? – Epsi95 Feb 19 '21 at 18:30
  • Or it could be true if both were boolean, and had the same boolean value. But the reality is, one is a list, the other a boolean, so it will never be true. – joao Feb 19 '21 at 18:51
  • 1
    "truthy" means will evaluate to true in a Boolean context (as the condition in an if), even it may return a different type (such as non-empty list) in a different context. – joao Feb 19 '21 at 18:52
0

I was curious about the first one i.e.

12 in [12,13,14] == True

Since it was giving False. So I did a little analysis.

class A:
    def __init__(self, a):
        self.a = a

    def __eq__(self, other):
        print(other)
        return other == self.a

12 in [12, print('I am in list'), 14] == A(True)

It prints

I am in list
[12, None, 14]
False

That means:

  1. 12 in [12, None, 14] is checked which gives True (where None is the return value of print())

  2. An equality is checked between [12, None, 14] and True

wjandrea
  • 28,235
  • 9
  • 60
  • 81
Epsi95
  • 8,832
  • 1
  • 16
  • 34
  • 2
    That `print()` is a red herring. It's evaluated before anything else is, so you could just substitute its return value, `None`. – wjandrea Feb 19 '21 at 17:55