Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h2>Short Answer</h2> <p>In Python 2.x, the <code>str</code> type holds raw bytes, so <code>dis</code> assumes that if you pass it a string it is getting compiled bytecode. It tries to disassemble the string you pass it as bytecode and -- purely due to the implementation details of Python bytecode -- succeeds for <code>i in (2,3)</code>. Obviously, though, it returns gibberish.</p> <p>In Python 3.x, the <code>str</code> type is for <em>strings</em> and the <code>bytes</code> types is for raw bytes, so <code>dis</code> can distinguish between compiled bytecode and strings -- and assumes it is getting source code if it gets a string.</p> <hr> <h2>Long Answer</h2> <p>Here's the thought process I followed to work this one out.</p> <ol> <li><p>I tried it on my Python (3.2):</p> <pre><code>&gt;&gt;&gt; import dis &gt;&gt;&gt; dis.dis("i in (2,3)") 1 0 LOAD_NAME 0 (i) 3 LOAD_CONST 2 ((2, 3)) 6 COMPARE_OP 6 (in) 9 RETURN_VALUE &gt;&gt;&gt; dis.dis("i in [2,3]") 1 0 LOAD_NAME 0 (i) 3 LOAD_CONST 2 ((2, 3)) 6 COMPARE_OP 6 (in) 9 RETURN_VALUE </code></pre> <p>Obviously, this works.</p></li> <li><p>I tried it on Python 2.7:</p> <pre><code>&gt;&gt;&gt; import dis &gt;&gt;&gt; dis.dis("i in (2,3)") 0 BUILD_MAP 26912 3 JUMP_FORWARD 10272 (to 10278) 6 DELETE_SLICE+0 7 &lt;44&gt; 8 DELETE_SLICE+1 9 STORE_SLICE+1 &gt;&gt;&gt; dis.dis("i in [2,3]") Traceback (most recent call last): File "&lt;stdin&gt;", line 1, in &lt;module&gt; File "C:\Python27\lib\dis.py", line 45, in dis disassemble_string(x) File "C:\Python27\lib\dis.py", line 112, in disassemble_string labels = findlabels(code) File "C:\Python27\lib\dis.py", line 166, in findlabels oparg = ord(code[i]) + ord(code[i+1])*256 IndexError: string index out of range </code></pre> <p>Aha! Notice also that the generated bytecode in Python 3.2 is what you would expect ("load <code>i</code>, load <code>(2,3)</code>, test for membership, return the result") whereas what you have got in Python 2.7 is gibberish. Clearly, <code>dis</code> is decompiling the string as bytecode in 2.7 but compiling it as Python in 3.2.</p></li> <li><p>I had a look in the source code for <code>dis.dis</code>. Here are the key points:</p> <p>Python 2.7:</p> <pre><code>elif isinstance(x, str): disassemble_string(x) </code></pre> <p>Python 3.2:</p> <pre><code> elif isinstance(x, (bytes, bytearray)): # Raw bytecode _disassemble_bytes(x) elif isinstance(x, str): # Source code _disassemble_str(x) </code></pre> <p>Just for fun, let's check this by passing the same bytes to <code>dis</code> in Python 3:</p> <pre><code>&gt;&gt;&gt; dis.dis("i in (2,3)".encode()) 0 BUILD_MAP 26912 3 JUMP_FORWARD 10272 (to 10278) 6 &lt;50&gt; 7 &lt;44&gt; 8 &lt;51&gt; 9 &lt;41&gt; </code></pre> <p>Aha! Gibberish! (Though note that it's slightly different gibberish -- the bytecode has changed with the Python version!)</p></li> </ol>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload