homepage

This issue tracker has been migrated to GitHub , and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Operator issue with "in" on same level and preceding ==
Type: behavior Stage: resolved
Components: Interpreter Core Versions: Python 3.4, Python 3.5, Python 2.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: Sapphire Becker, ezio.melotti
Priority: normal Keywords:

Created on 2015年10月26日 16:08 by Sapphire Becker, last changed 2022年04月11日 14:58 by admin. This issue is now closed.

Messages (3)
msg253478 - (view) Author: Sapphire Becker (Sapphire Becker) Date: 2015年10月26日 16:08
So I found this while using == as xnor, here's a summary of the issue:
>>> "h" in ["h"] == True
False
>>> ("h" in ["h"]) == True
True
>>> "h" in (["h"] == True)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: argument of type 'bool' is not iterable
Now obviously #3 should error but I would expect #1 and #2 to be the same. I checked it out with dis (in Py 3.4) and it seems like a bug. In detail:
#2's is very clean, exactly what I would expect:
>>> dis.dis('("h" in ["h"]) == True')
 1 0 LOAD_CONST 0 ('h')
 3 LOAD_CONST 2 (('h',))
 6 COMPARE_OP 6 (in)
 9 LOAD_CONST 1 (True)
 12 COMPARE_OP 2 (==)
 15 RETURN_VALUE
#1's, however, looks like a mess:
>>> dis.dis('"h" in ["h"] == True')
 1 0 LOAD_CONST 0 ('h')
 3 LOAD_CONST 0 ('h')
 6 BUILD_LIST 1
 9 DUP_TOP
 10 ROT_THREE
 11 COMPARE_OP 6 (in)
 14 JUMP_IF_FALSE_OR_POP 24
 17 LOAD_CONST 1 (True)
 20 COMPARE_OP 2 (==)
 23 RETURN_VALUE
 >> 24 ROT_TWO
 25 POP_TOP
 26 RETURN_VALUE
I had to write out the stack to understand this:
1. ['h']
2. ['h', 'h']
3. ['h', ['h']]
4. ['h', ['h'], ['h']]
5. [['h'], 'h', ['h']]
6. [['h'], True] # True = result of in operation
7. [['h']]
8. [['h'], True] # True = =='s right-hand value
9. [False] # False = result of == operation
Therefore the way to actually get true in the first case is:
>>> "h" in ["h"] == ["h"]
True
I won't pretend to know how simple it is in Python's architecture but I imagine it's just setting a higher precedence for "in" than ==?
Not a huge deal, it's workaroundable, just awkward that there wasn't really any indication it was failing so it took a bit to debug.
msg253479 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2015年10月26日 16:50
As far as I understand, this is treated as "x < y < z" or "x == y == z":
>>> import ast
>>> ast.dump(ast.parse("1 < 2 < 3"))
'Module(body=[Expr(value=Compare(left=Num(n=1), ops=[Lt(), Lt()], comparators=[Num(n=2), Num(n=3)]))])
>>> ast.dump(ast.parse("1 == 2 == 3"))
'Module(body=[Expr(value=Compare(left=Num(n=1), ops=[Eq(), Eq()], comparators=[Num(n=2), Num(n=3)]))])'
>>> ast.dump(ast.parse("1 in 2 == 3"))
'Module(body=[Expr(value=Compare(left=Num(n=1), ops=[In(), Eq()], comparators=[Num(n=2), Num(n=3)]))])'
The following code is also valid and works as expected:
>>> 1 in [1] in [[1]]
True
>>> 2 not in [1] in [[1]]
True
Your example yields an unexpected result, but I'm not sure if and how it can be fixed.
msg253482 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2015年10月26日 17:15
https://docs.python.org/3/reference/expressions.html#comparisons says that "a op1 b op2 c ... y opN z is equivalent to a op1 b and b op2 c and ... y opN z" and this explains the "unexpected" result:
>>> 1 in [1] == True
False
>>> 1 in [1] and [1] == True
False
"in" and "not in" are also listed among the comparison operators, so I think this behavior is expected and by design. I don't think there's anything that needs to be fixed here.
History
Date User Action Args
2022年04月11日 14:58:23adminsetgithub: 69670
2015年10月26日 17:15:31ezio.melottisetstatus: open -> closed
resolution: not a bug
messages: + msg253482

stage: resolved
2015年10月26日 16:50:28ezio.melottisetmessages: + msg253479
2015年10月26日 16:39:47ezio.melottisetnosy: + ezio.melotti

versions: + Python 3.5
2015年10月26日 16:08:58Sapphire Beckercreate

AltStyle によって変換されたページ (->オリジナル) /