+ 2
Help me with this expression in python 3
I have this code: arr = [True, "a"]; print("a" in arr in arr) output: false why? "a" is in the arr, so the first result should be True, after that True is in arr, so the output should be True, why the output is false? or what is the way that python works to throw false?
8 Answers
+ 6
From disassembly, it looks like the first "in" returns False (which I believe to be the "arr in arr" test, since that makes it work in my previous answer), then short-circuit boolean evaluation occurs at 26: JUMP_IF_FALSE_OR_POP and "a" in False (which should throw a "TypeError / not iterable" exception) never happens.
Here's a test forcing both evaluations when arr is not appended to itself:
arr=[True, 'a']
print('a' in (arr in arr))
TypeError: argument of type 'bool' is not iterable
0-18...same as above...
21 LOAD_NAME 0 (0)
24 COMPARE_OP 6 (in)
27 COMPARE_OP 6 (in)
30 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
33 POP_TOP
34 LOAD_CONST 2 (2)
37 RETURN_VALUE
+ 5
arr.append(arr)
That makes it work, I don't exactly know why yet (the answer to "arr in arr" is not iterable).
This works too:
print(("a" in arr) in arr)
+ 5
This is from my disassembler here (for anyone interested, otherwise just ignore)
~~Source
arr=[True, 'a']
print('a' in arr in arr)
~~About the bytecode:
Name:<module> Filename:<string> Argument count:0 Kw-only arguments:0 Number of locals:0 Stack size:4 Flags:NOFREE
Constants:
0: True
1: 'a'
2: None
Names:
0: arr
1: print
~~Disassembled bytecode:
0 LOAD_CONST 0 (0)
3 LOAD_CONST 1 (1)
6 BUILD_LIST 2
9 STORE_NAME 0 (0)
12 LOAD_NAME 1 (1)
15 LOAD_CONST 1 (1)
18 LOAD_NAME 0 (0)
21 DUP_TOP
22 ROT_THREE
23 COMPARE_OP 6 (in)
26 JUMP_IF_FALSE_OR_POP 38
29 LOAD_NAME 0 (0)
32 COMPARE_OP 6 (in)
35 JUMP_FORWARD 2 (to 40)
>>38 ROT_TWO
39 POP_TOP
>>40 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
43 POP_TOP
44 LOAD_CONST 2 (2)
47 RETURN_VALUE
+ 3
I'm no Python guru, nor do I even like the language, so take what I say with a grain of salt. Does Python normally make you put "in arr" twice like that? If not, remove the second "in arr" and it should return true.
+ 3
Jay Matthews With no imports, the __code__ attribute provides compiled bytecode for live objects (like function.__code__). The "dis" import has functions related to bytecode / disassembly, and the "marshal" import can import external bytecode into a running program.
+ 2
Jay Mathews may be right, I tried. Please check the code below.
https://code.sololearn.com/cH866wVxy5hE/?ref=app
+ 2
Venkatesha P I don't think "a" in False is ever evaluated
0
Kirk Schafer wonderful explanation, thank you so much!