[Tutor] Class and Scope Question

Karl Pflästerer sigurd at 12move.de
Fri May 6 14:44:07 CEST 2005


On  6 Mai 2005, tim at johnsons-web.com wrote:

>
> The following test script is kind of got me baffled:
>#!/usr/local/bin/python
> class Eval:
>     def __getitem__(self,key):
>         return eval(key)
>##def test():
>##  i = 100
>##  b = ["My", "name", "is", "Tim"]
>##  test = "this is number %(str(i))s for a test %(' '.join(b))s"
>##  s = test % Eval()
>##  print s
>##test()
> i = 100
> b = ["My", "name", "is", "Tim"]
> test = "this is number %(str(i))s for a test %(' '.join(b))s"
> print test % Eval()
>## ============================================================
> Running this gives me the following :
> [tim at linus baker]$ python test.py
> this is number 100 for a test My name is Tim
>## cool!
> Now if I comment out the last four lines and uncomment
> the previous 7, I get the following error message:
> [tim at linus baker]$ python test.py
> Traceback (most recent call last):
>   File "test.py", line 11, in ?
>     test()
>   File "test.py", line 9, in test
>     s = test % Eval()
>   File "test.py", line 4, in __getitem__
>     return eval(key)
>   File "<string>", line 0, in ?
> NameError: name 'i' is not defined
>## It's been a lloooonngg day. What am I missing here?
> Explanation and solution is no doubt going to further edify
> me about python.

If you look in the Python reference manual under 
'Execution model -> Naming and binding -> Interaction with dynamic features'
you will find the following paragraph:

,----
| The `eval()', `execfile()', and `input()' functions and the `exec'
| statement do not have access to the full environment for resolving
| names.  Names may be resolved in the local and global namespaces of the
| caller.  Free variables are not resolved in the nearest enclosing
| namespace, but in the global namespace.(1) The `exec' statement and the
| `eval()' and `execfile()' functions have optional arguments to override
| the global and local namespace.  If only one namespace is specified, it
| is used for both.
| 
| ---------- Footnotes ----------
| 
| (1) This limitation occurs because the code that is executed by these
| operations is not available at the time the module is compiled.
`----

So you had a free variable `i' which was in your first example found in
the global namespace but in your second example it existed only in the
local namespace.  So it wasn't found by `eval'.  You could write your
class definition so that you call eval with the correct environment.

E.g. :

class Eval (object):
    def __init__(self, Globals = globals(), Locals = locals()):
        self.Globals = Globals
        self.Locals = Locals
    def __getitem__(self,key):
        return eval(key, self.Globals, self.Locals)

Then your function definition could become:

def test():
  i = 100
  b = ["My", "name", "is", "Tim"]
  test = "this is number %(str(i))s for a test %(' '.join(b))s"
  s = test % Eval(Locals=locals())
  print s




   Karl
-- 
Please do *not* send copies of replies to me.
I read the list


More information about the Tutor mailing list