properties vs. eval()

B

Bob Rogers

Given this class:

class C(object):
def set_x(self, x):
self._x = x

def get_x(self):
return self._x

x = property(get_x, set_x)


This use of compile() and eval() works as I expected it to:

c = C()
c.x = 5000
n = '\'five thousand\''
code = compile('c.x = ' + n, '<input>', 'exec')
print 'before ', c.x
eval(code)
print 'after ', c.x

But this, using eval() without compile(), does not:

c = C()
c.x = 5000
n = '\'five thousand\''
print 'before ', c.x
eval('c.x = ' + n)
print 'after ', c.x

It gives:

before 5000
Traceback (most recent call last):
File "./r.py", line 16, in ?
eval('c.x = ' + n)
File "<string>", line 1
c.x = 'five thousand'
^
SyntaxError: invalid syntax

Could someone please explain just what is going on here, and whether it
is possible to dispense with the compile step and use eval() alone
while setting a property?

Thanks.
 
P

Peter Otten

Bob said:
Given this class:

class C(object):
def set_x(self, x):
self._x = x

def get_x(self):
return self._x

x = property(get_x, set_x)


This use of compile() and eval() works as I expected it to:

c = C()
c.x = 5000
n = '\'five thousand\''
code = compile('c.x = ' + n, '<input>', 'exec')
print 'before ', c.x
eval(code)
print 'after ', c.x

I believe it is an implementation accident that this works.
But this, using eval() without compile(), does not:

c = C()
c.x = 5000
n = '\'five thousand\''
print 'before ', c.x
eval('c.x = ' + n)
print 'after ', c.x

It gives:

before 5000
Traceback (most recent call last):
File "./r.py", line 16, in ?
eval('c.x = ' + n)
File "<string>", line 1
c.x = 'five thousand'
^
SyntaxError: invalid syntax

Could someone please explain just what is going on here, and whether it
is possible to dispense with the compile step and use eval() alone
while setting a property?

Use

eval(s)

to evaluate an expression and

exec s

to execute a statement.

Peter
 
M

Michael Hoffman

Peter said:
Use

eval(s)

to evaluate an expression and

exec s

to execute a statement.

I never thought of using compile() to get around this before. Now I can
finally use print in my lambda functions! Just think of the horrible
code I could write:

f = lambda x: eval(compile("print %s" % x, "<string>", "exec"))
 
J

Jason Mobarak

Why are you using eval in the first place? This isn't bash. Use setattr
and getattr for dynamic attribute access.
 
B

Bob Rogers

So you're saying you don't know the answer? The question wasn't
"should I use setattr?"
 
S

Steve Holden

Bob said:
So you're saying you don't know the answer? The question wasn't
"should I use setattr?"
No, the "*question*" was (paraphrasing slightly) "is [it] possible to
dispense with the compile step and use eval() alone while setting a
property" the *answer* was "you should use setattr".

If you don't see that this implies that using eval() is not a good idea
until other resources have been exhausted, then you need to understand:
"using eval() is not a good idea until other resources have been exhausted".

regards
Steve
 
J

Jason Mobarak

Bob said:
So you're saying you don't know the answer? The question wasn't
"should I use setattr?"

If what you're doing is wrong and backwards then it doesn't matter what
the question is. Best practices are best practices for a reason.
There's no reason to use eval to do what you want. The constructs
eval/exec/compile all have their purposes (for example: a remote python
shell) but they weren't intended to be broken replacements for setattr.
 

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,769
Messages
2,569,582
Members
45,067
Latest member
HunterTere

Latest Threads

Top