17

The following comparisons produce True:

>>> '1' in '11'
True
>>> ('1' in '11') == True
True

And with the parentheses the other way, I get a TypeError:

>>> '1' in ('11' == True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: argument of type 'bool' is not iterable

So how do I get False with no parentheses?

>>> '1' in '11' == True
False
user2357112
  • 260,549
  • 28
  • 431
  • 505
nobody
  • 181
  • 4

3 Answers3

23

The Python manual says in and == are of equal precedence. Thus, they're evaluated from left to right by default, but there's also chaining to consider. The expression you put above ('1' in '11' == True) is actually being evaluated as...

('1' in '11') and ('11' == True)

which of course is False. If you don't know what chaining is, it's what allows you to do something like...

if 0 < a < 1:

in Python, and have that mean what you expect ("a is greater than 0 but less than 1").

wjandrea
  • 28,235
  • 9
  • 60
  • 81
Amber
  • 507,862
  • 82
  • 626
  • 550
9

It has nothing to do with precedence. In Python relational operators chain, and containment is considered a relational operator. Therefore:

'1' in '11' == True

is the same as:

('1' in '11') and ('11' == True)

which is false since True is not equal to "11".

wjandrea
  • 28,235
  • 9
  • 60
  • 81
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
2

Chaining allows you to write x < y < z, and mean x < y and y < z. Look at this interaction:

>>> (False == True) == False
True
>>> False == (True == False)
True
>>> False == True == False
False
>>>

So in your example, '1' in '11' == True is equivalent to ('1' in '11') and ('11' == True)

Roshan Mathews
  • 5,788
  • 2
  • 26
  • 36