On Sat, 28 Oct 2006 15:29:39 -0500, David Harvey  
<[EMAIL PROTECTED]> wrote:
> On Oct 28, 2006, at 2:50 PM, William Stein wrote:
>
>> You might think you could do:
>>
>> def func1():
>>      T = QQ["x"]
>>      # do some calculations with T
>>      func2()
>>      # do some calculations with T
>>
>> def func2():
>>      S = ZZ["x"]
>>       S.inject_variables(locals())
>>       print x^3 + 5
>>
>> and it would work and not touch func1's x.  This doesn't work, because
>> locals() is merely a *copy* of the local variables.  Python doesn't
>> allow changing of locals(), probably for "compiler" reasons.
>
> I've just been studying the python 2.5 source, trying to figure out
> whether it's possible to inject local variable names as we want to
> do. My conclusion is that it's basically impossible, from python or
> even from C.
>
> The problem is that the python byte-code interpreter usually *doesn't
> even see the local variable names*. What seems to happen is that the
> byte-code compiler identifies all the local variables at parse time,
> and assigns each of them an integer index. For example, if I take
> this function:
>
> def f():
>     x = 2
>     y = x
>
> Then I look at the byte-code:
>
>  >>> dis.dis(f)
>    2           0 LOAD_CONST               1 (2)
>                3 STORE_FAST               1 (x)
>
>    3           6 LOAD_FAST                1 (x)
>                9 STORE_FAST               0 (y)
>               12 LOAD_CONST               0 (None)
>               15 RETURN_VALUE
>
> The stuff in parentheses is for the reader's convenience; it's not
> actually in the bytecode. The bytecode only has the indices.
>
> So if I try anything like this:
>
> def f():
>     try_to_inject_heroin_into_my_namespace()
>     print heroin
>
> It's doomed to fail, because the byte-code interpreter doesn't even
> look up the name "heroin". And there isn't any way that
> try_to_inject_heroin_into_my_namespace() can trick it, because the
> parser has *already decided* that "heroin" is global, even before
> try_to_inject_heroin_into_my_namespace() gets called. Here's the
> bytecode:
>
>    2           0 LOAD_GLOBAL              0
> (try_to_inject_heroin_into_my_namespace)
>                3 CALL_FUNCTION            0
>                6 POP_TOP
>
>    3           7 LOAD_GLOBAL              1 (heroin)
>               10 PRINT_ITEM
>               11 PRINT_NEWLINE
>               12 LOAD_CONST               0 (None)
>               15 RETURN_VALUE
>
> Bummer.
>
> (Well I guess you *could* write something that goes back and changes
> the byte-code.... heh....)

Another approach if you think this is worth pursuing would be to use the
brand new Python 2.5 "with" statement.   Let the globals() for the
module where the code is get changed, but store the old values of
variables.  Then at the end of the with block, restore all old values
of variables.    So we'd have code like this, which could be used in
any Python code.
------------------------
x = 5
# vars would be a context manager that inject's all the gens of its args
R = QQ['x,y']
S = PolynomialRing(QQ,'x', 50)   # vars are x0, x1, ..., x49
with vars(R, S):
     do arithmetic with x, y,  x37, etc.

print y, x10   # error -- they are no longer defined.
print x
-----------------------

I've never written a context manager, so I don't know 100% whether this
will work, but I bet it will.  I would try right now, but I have to create
the Arizona Winter School web page.

  PLUG -- Come to the Arizona Winter School!   I'm an organizer; Kiran  
Kedlaya
  is one of the speakers. It will rock!

William

--~--~---------~--~----~------------~-------~--~----~
To post to this group, send email to sage-devel@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/sage-devel
URLs: http://sage.scipy.org/sage/ and http://modular.math.washington.edu/sage/
-~----------~----~----~----~------~----~------~--~---

Reply via email to