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.
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:23 | admin | set | github: 69670 |
| 2015年10月26日 17:15:31 | ezio.melotti | set | status: open -> closed resolution: not a bug messages: + msg253482 stage: resolved |
| 2015年10月26日 16:50:28 | ezio.melotti | set | messages: + msg253479 |
| 2015年10月26日 16:39:47 | ezio.melotti | set | nosy:
+ ezio.melotti versions: + Python 3.5 |
| 2015年10月26日 16:08:58 | Sapphire Becker | create | |