eval function not working how i want it dag namn

R

robcarlton

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

thanks
 
M

Michael Hoffman

robcarlton said:
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)

That works fine for me with Python 2.4.

This is the best way to do it:

def list_members(obj):
return [getattr(obj, name) for name in dir(obj)]

Although personally I would prefer to have this information in dict
form, so i'd use:

return dict((name, getattr(obj, name)) for name in dir(obj))

For objects defined in CPython, you can use obj.__dict__, but this is
somewhat hacky, and I'd avoid it.
 
G

Gerald Klix

How about using the vars builtin?

Michael said:
robcarlton said:
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)


That works fine for me with Python 2.4.

This is the best way to do it:

def list_members(obj):
return [getattr(obj, name) for name in dir(obj)]

Although personally I would prefer to have this information in dict
form, so i'd use:

return dict((name, getattr(obj, name)) for name in dir(obj))

For objects defined in CPython, you can use obj.__dict__, but this is
somewhat hacky, and I'd avoid it.
 
P

Peter Otten

robcarlton said:
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:
.... return eval("obj")
....'x'

but with the lambda you are introducing a nested namespace.
.... return (lambda: eval("obj"))()
....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 g(): # no obj in g()'s namespace
.... return eval("obj")
.... return g()
....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 g():
.... obj # now you can see me
.... return eval("obj")
.... return g()
....'x'

Here's another way that is viable with lambda, too.
.... return (lambda obj=obj: eval("obj"))()
....'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:
.... return [getattr(obj, name) for name in dir(obj)]
....
import os
list_members(os)[:5] [73, 78, 65, 74, 68]

Peter
 
P

Peter Otten

Michael said:
That works fine for me with Python 2.4.

Python 2.4 (#6, Jan 30 2005, 11:14:08)
[GCC 3.3.3 (SuSE Linux)] on linux2
Type "help", "copyright", "credits" or "license" for more information..... l = dir(obj)
.... return map(lambda x: eval("obj." + x), l)
........ pass
....Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in lm
File "<stdin>", line 3, in <lambda>

Peter
 
M

Michael Hoffman

I should clarify. It works fine for me when I've already globally
assigned obj to something else. D'oh!
 
R

robcarlton

thanks. I'll use the getattr function now, and I think I understand
where I went wrong with eval. I was thinking in Lisp where the lexical
scope would mean that obj is defined
 
G

Greg Ewing

robcarlton said:
thanks. I'll use the getattr function now, and I think I understand
where I went wrong with eval. I was thinking in Lisp where the lexical
scope would mean that obj is defined

The full story is actually more subtle. The name 'obj'
*is* accessible from a nested scope if you do something
like

def f(obj):
def g():
print obj
g()

But the bytecode compiler has to do extra work to make
a name in an intermediate scope accessible to an inner
scope, and it only does this if it sees a reference to
the name in the inner scope. In your code, the reference
is invisible at compile time, so the compiler misses it,
and the run-time evaluation fails.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top