code blocks in Python

Hung Jung Lu hungjunglu at yahoo.com
Sun Nov 23 18:43:31 CET 2003


bokr at oz.net (Bengt Richter) wrote in message news:<bppdph$s4u$0 at 216.39.172.122>...
> 
>  >>> compile('a=123','','single')
>  <code object ? at 0090D5A0, file "", line 1>
>  >>> import dis
>  >>> dis.dis(compile('a=123','','single'))
>    1           0 LOAD_CONST               0 (123)
>                3 STORE_NAME               0 (a)
>                6 LOAD_CONST               1 (None)
>                9 RETURN_VALUE
>  >>> def foo(): a=123
>  ...
>  >>> dis.dis(foo)
>    1           0 LOAD_CONST               1 (123)
>                3 STORE_FAST               0 (a)
>                6 LOAD_CONST               0 (None)
>                9 RETURN_VALUE
> 
> So which code will you want when the compiler compiles an in-context block?

> Will you want it to be a first-class object? 

Yes, absolutely.

> with compile's output? Are you willing to forego the optimized local access? 

I know there is a performance issue, since in normal, local, non-named
codeblocks, local variables are retrieved by indices instead of names.
There is a question as how to hook up named codeblocks efficiently in
the scope of the non-named codeblocks. But one is gotta start
somewhere. Optimization comes later.

> You could call for magic creation of special
> closures so that an exported code block would still refer back to the local name space
> (which BTW could be interesting for generators to yield, to give external access to their
> internal state). 

Again, something simple to start with. Closures comes later, if at all
necessary. I am not sure whether closure-like codeblocks are
fundamental enough, since they could be emulated by other means. E.g.

class generic: pass

codeblock A:
    print c.x
    c.x = 3

c1 = generic()
c2 = generic()
c1.x = 4
c1.code = A
c2.x = 5
c2.code = A

c = c1
exec c.code

c = c2
exec c.code

> And what should assigning a function local codeblock to a global mean?
> Maybe creating a one-shot generator where the codeblock could be used to preset state for
> a single ordinary function call that re-uses previous state. Or should it just die like a
> weak reference?

I don't know exactly what you mean by "function local codeblock". If
you refer to the function's code, currently accessible as f.func_code,
I've tried that, but it seems to bind things to the locals dictionary
of the function itself. Which is no good. E.g.:

def f():
    x = 1

def g(x):
    exec f.func_code
    print x

g(2)
x = 3
exec f.func_code in globals()
print x

will print 2 and 3. I tried using exec...in... with various
namespaces, but the same thing. That is, the func_code remembers its
own local scope and refuses access/modify other local scopes. This is
very different from:

code = compile('x=1\n', '<string>', 'exec')

def g(x):
    exec code
    print x

g(2)
x = 3
exec code
print x

which will print 1 and 1. That is, smart enough to take x from the
respective local and global dictionaries.

----------

If by "function local codeblock" you mean codeblocks define inside the
scope of a function, I really don't think they should receive any
special treatment for optimization, since a codeblock should be an
object that can be passed around, and should be independent of where
they are defined. It's like if you have the number 3, which is an
object, you can pass it around to anywhere, regardless where it was
first defined. No complications from nested-scopes, closures, etc.
Functions get complicated exactly because they carry all these extra
baggages.

----------

Well, all these are the kinds of things to think about. But named
codeblocks have well-defined meaning on their own right, independent
of implementation details. Theoretically, codeblocks don't know
whether the names inside them are local or global. It's a late-binding
object.

> but I wonder how common/important they are.

I can't say in the case you have described. However, in general
codeblocks are extremely useful, right now they are not used as
widely, I think simply because the codestrings are not compiled and
checked at compile time: you need one extra step invoking the
compile() function. Named codeblocks will solve a barrage of nuisances
in today's programming world. They helps in (a) code re-use, (b) code
modularization. By (a) I mean that the same codeblock could be used in
a lot of places. By (b) I mean that you can isolate the effects of
codeblocks, and do code replacements a la AOP (Aspect-Oriented
Programming.)

It's just weird that Python has the compile() function, but has no
named codeblocks. I really can't understand why.

regards,

Hung Jung




More information about the Python-list mailing list