code blocks in Python

Bengt Richter bokr at oz.net
Sat Nov 22 23:41:21 EST 2003


On 22 Nov 2003 19:13:19 -0800, hungjunglu at yahoo.com (Hung Jung Lu) wrote:

>"John Roth" <newsgroups at jhrothjr.com> wrote in message news:<vrvjpt7fh4lob8 at news.supernews.com>...
>> Just some random observations. First, I'm not at all clear on
>> what you want it to do. Some examples would be helpful. There
>> are entirely too many different ways I could interpret your reference
>> to metaprogramming for me to understand the usage you have in
>> mind.
>
>codeblock A:
>    x = 1
>    y = 2
>
>codeblock B:
>    z = x + y
>    print z
>
>exec A
>exec B
>
>This will be equivalent to writing the program:
>
>x = 1
>y = 2
>z = x + y
>print z
>
>> If you want it as a replacement for the badly crippled lambda statement,
>> then I think there's quite a bit of interest. What's holding that up is
>> syntax, and an appropriate syntax isn't entirely obvious.
>
>Lambda is a totally different thing. Lambda is an anonymous
>*function*. I emphasize *function* because functions take parameters
>and return values. Code blocks are, well, blocks of code. No
>parameters, no nothing else. Simple and plain blocks of code. Once you
>have codeblocks, you wire them anyway you want. Think of them as
>macros in C++, only that in Python you can wire them dynamically
>during runtime. Python already does that. It's just that you need the
>compile() function, your code string is not compiled until the
>compile() function is executed, and the resulting object type is
>"Code" (which is a fine name, even if the new keyword were
>"codeblock".) Have you tried the compile() function?
>
I note that:

 >>> 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? Should you be able to
pass the code-block name to an arbitrary function or bind it globally, like you can
with compile's output? Are you willing to forego the optimized local access? Or want to
exec it later from anywhere? What should happen? 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). 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?

IOW, there are some things to think about, because the semantics could get interesting ;-)
It would be nice to have efficient local blocks, so you could write exec(locals()[switcharg])
or perhaps some more efficient builtin switch/case thing using them. The efficiency of
a large jump table (dict or tuple/list based) vs a chain of elifs is a good motivation for some uses,
but I wonder how common/important they are.

Regards,
Bengt Richter




More information about the Python-list mailing list