[Tutor] Class and Scope Question
Rich Krauter
rmkrauter at yahoo.com
Fri May 6 14:07:13 CEST 2005
Tim Johnson 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.
>
> TIA
> tim
>
Tim,
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 has a more
general solution in the comments at the bottom. Basically, you need to
put an __init__ in the Eval class, pass locals() and globals() to it,
and use those passed-in values in your call to the eval() built-in.
I believe the result you see is due to python's lexical scoping rules.
Scope is determined by a function- or class-definition's position in the
text of the program.
<example>
def f():
x = 20
def g():
print x
g()
def h():
x = 50
i()
def i():
print x
if __name__ == '__main__':
f() # works
h() # doesn't work
</example>
Here's another example:
<example>
g = 'module level'
class A:
def print_locals_and_globals(self):
for k,v in locals().items()+globals().items():
print k,v
def func():
# a couple names that won't appear
# in a's locals or globals
i = 10
s = 'a string'
a = A()
a.print_locals_and_globals()
if __name__ == '__main__':
func()
</example>
So it seems the locals and globals visible to an instance of a class is
determined by where the class is defined, not by where the instance is
created.
HTH,
Rich
More information about the Tutor
mailing list