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