eval function not working how i want it dag namn

Peter Otten __peter__ at web.de
Fri Apr 15 11:33:20 EDT 2005


robcarlton wrote:

> hi everybody
> I've written this function to make a list of all of an objects
> attributes and methods (not for any reason, I'm just learning)
> 
> def list_members(obj)
>     l = dir(obj)
>     return map(lambda x : eval('obj.'+x), l)
> 
> but I get an error saying that obj isn't defined. As I understand it
> eval has access to the current local namespace, which does contain
> object, so I'm not sure whats going wrong.
> 
> ps Im sure there are better ways of doing the above which doesn't call
> the eval function, and while I'd be glad to know what it is, I'd still
> like to understand why my way isnt working

It would work if obj were in the local namespace like so:

>>> def f(obj="x"):
...     return eval("obj")
...
>>> f()
'x'

but with the lambda you are introducing a nested namespace.

>>> def f(obj="x"):
...     return (lambda: eval("obj"))()
...
>>> f()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 2, in f
  File "<stdin>", line 2, in <lambda>
  File "<string>", line 0, in ?
NameError: name 'obj' is not defined

You are doing the equivalent to

>>> def f(obj="x"):
...     def g(): # no obj in g()'s namespace
...             return eval("obj")
...     return g()
...
>>> f()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 4, in f
  File "<stdin>", line 3, in g
  File "<string>", line 0, in ?
NameError: name 'obj' is not defined

only in a convoluted way. Let's make f()'s local variable obj visible in
g(), too:

>>> def f(obj="x"):
...     def g():
...             obj # now you can see me
...             return eval("obj")
...     return g()
...
>>> f()
'x'

Here's another way that is viable with lambda, too. 

>>> def f(obj="x"):
...     return (lambda obj=obj: eval("obj"))()
...
>>> f()
'x'

I'm sure you can fix your list_members() accordingly. Note that rebinding
obj between the definition and call of g() will affect the result only in
the first of the last two examples. 

And now for something completely different:

>>> def list_members(obj):
...     return [getattr(obj, name) for name in dir(obj)]
...
>>> import os
>>> list_members(os)[:5]
[73, 78, 65, 74, 68]
>>>

Peter




More information about the Python-list mailing list