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.
|