[Edu-sig] Peeking under the hood
Kirby Urner
pdx4d@teleport.com
Sun, 17 Jun 2001 22:36:01 -0700
And now for something completely different...
Let's help give students a sense of what it means to say
"in Python, user-defined functions compile to bytecodes".
Here's a silly function to remove an item from a list, or
not care if it ain't there. This one's "in place" (returns
nothing).
>>> def rem(L,i):
try: L.remove(i)
except ValueError: pass
>>> mylist = ['C','A','T']
>>> rem(mylist,'C')
>>> mylist
['A', 'T']
>>> rem(mylist,'X')
>>> mylist
['A', 'T']
The code object corresponding to this function may be dumped
as an attribute of rem:
>>> rem.func_code
<code object rem at 00B7EE80, file "<pyshell#24>", line 1>
Let's look at the bytecodes:
>>> rem.func_code.co_code
'\x7f\x01\x00\x7f\x02\x00y\x17\x00\x7f\x02\x00|\x00\x00i
\x01\x00d\x01\x00d\x02\x00\x83\x00\x01\x01Wn\x19\x00\x7f
\x03\x00\x04t\x02\x00j\n\x00o\n\x00\x01\x01\x01\x01\x7f
\x03\x00n\x02\x00\x01Xd\x00\x00S'
The dis module lets you disassemble bytecodes into something
more readable (if not the original Python source):
>>> import dis
>>> import pydoc
>>> pydoc.help(dis)
Help on module dis:
NAME
dis - Disassembler of Python byte code into mnemonics.
FILE
d:\program files\python21\lib\dis.py
DATA
<<SNIP>>
>>> dis.disassemble(rem.func_code)
0 SET_LINENO 1
3 SET_LINENO 2
6 SETUP_EXCEPT 23 (to 32)
9 SET_LINENO 2
12 LOAD_FAST 0 (L)
15 LOAD_ATTR 1 (remove)
18 LOAD_CONST 1 ('i')
21 LOAD_CONST 2 (0)
24 CALL_FUNCTION 256
27 POP_TOP
28 POP_BLOCK
29 JUMP_FORWARD 25 (to 57)
>> 32 SET_LINENO 3
35 DUP_TOP
36 LOAD_GLOBAL 2 (ValueError)
39 COMPARE_OP 10 (exception match)
42 JUMP_IF_FALSE 10 (to 55)
45 POP_TOP
46 POP_TOP
47 POP_TOP
48 POP_TOP
49 SET_LINENO 3
52 JUMP_FORWARD 2 (to 57)
>> 55 POP_TOP
56 END_FINALLY
>> 57 LOAD_CONST 0 (None)
60 RETURN_VALUE
Now that's something different.
Pieces missing in this story. Could be fleshed out. Like Arthur,
I like to peek under the hood sometimes.
Kirby