[Tutor] PyMOTW: difflib
Kent Johnson
kent37 at tds.net
Tue Apr 8 04:20:22 CEST 2008
Alan Gauld wrote:
> "Dick Moores" <rdm at rcblue.com> wrote
>
>> Could you give a blow-by-blow on the dis.dis()?
>
> I'll have a go but I've never actually studied Python P-Code,
> this is based on my 8080 and 68000 assembler experience!
Some hits, some misses. I'll correct to the best of my knowledge.
One thing you need to know is that the Python VM is a stack machine, not
register-based. Think Forth or Postscript, not 8080.
>
>> In [22]: def f(x):
>> ....: if x%2:
>> ....: return "odd"
>> ....: else:
>> ....: return "even"
>> ....:
>> ....:
>>
>> In [23]: dis.dis(f)
>> 2 0 LOAD_FAST 0 (x)
>> 3 LOAD_CONST 1 (2)
>
> load x and 2 into two temporary storage areas
> (registers in conventional assembler)
No, it pushes x and 2 onto the stack. 0 and 1 are the indices into the
local variable list (in the stack frame) and the function's constant
list (part of the function). The values in parentheses are helpful
comments by dis, not part of the code itself.
>
>> 6 BINARY_MODULO
>
> Do the modulo operation and store the result in a temporary
> location (accumulator in assembler)
The arguments are the top two items on the stack, the result is left on
the stack.
>
>> 7 JUMP_IF_FALSE 8 (to 18)
>
> If the result is zero(false)
Yes, but not the way you think it works. It is checking the top of the
stack (TOS in the docs), not some flag set by the modulo operation the
way an 8080 would.
> go to instruction 18
> (I don't know what the 8 signifies, I thought a
> program counter offset but that would make it
> a jump to 15...)
Probably an offset to the PC value of the next instruction. Again, the
part in parens is a helpful comment.
>
>> 10 POP_TOP
>
> else (ie modulo result is non zero) pop the top - I'm
> not sure what that does exactly but I assume it pops
> a value of some stack into the accumulator area?
Just pops the stack, the value is no longer needed after the test.
>
>> 3 11 LOAD_CONST 2 ('odd')
>> 14 RETURN_VALUE
>
> Load 'odd' into storage area 2 and then return it?
Load odd *from* offset 2 to the stack and return it.
>
>> 15 JUMP_FORWARD 5 (to 23)
>
> Not sure about this bit...
I think this is junk. The Python compiler does very little optimization,
even simple peephole optimizations. This looks like boilerplate code
emitted to skip the 'else' clause. The boilerplate is left in even
though the code is not reachable.
>
>> >> 18 POP_TOP
>
> This was target of our previous jump if false instruiction
>
>> 5 19 LOAD_CONST 3 ('even')
>> 22 RETURN_VALUE
>
> So it loads 'even' and then returns it to the caller.
>
>> >> 23 LOAD_CONST 0 (None)
>> 26 RETURN_VALUE
>
> I assume this is the default return value in case there is no
> other returns, so not used here.
More leftover junk.
BTW there are several recipes in the cookbook that rely on hacking the
bytecodes directly from Python. Here are some:
http://tinyurl.com/6xn55p
This one by Raymond Hettinger optimizes references to globals by
automatically converting them to references to locals. "The speed-up is
substantial (trading one or more dictionary lookups for a single C-speed
array lookup)."
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/277940
Kent
More information about the Tutor
mailing list