variables exist

F

Fredrik Lundh

fabian said:
how testing if a variable exists in python as isset in php??

try:
variable
except NameError:
print "variable not set"

but that is really lousy Python; better make sure you always assign to
all variables, and use None (or another suitable value) to mark that some
variable has no meaningful content right now.

that is, instead of

if condition:
variable = 1

...

try:
variable
except NameError:
....

write

variable = None

if condition:
variable = 1

...

if variable is None:
print "variable not set"

</F>
 
G

Gerald Klix

try:
myVariable
except NameError:
print "Not bound"
else:
print "Bound"

If you want to distinguish between the local an the global environment:

if globals().has_key( "myVariable" ):
...

versus

if locals().has_key( ".....


HTH,
Gerald
 
B

Brian van den Broek

Fredrik Lundh said unto the world upon 2005-04-11 10:14:
try:
variable
except NameError:
print "variable not set"

but that is really lousy Python; better make sure you always assign to
all variables, and use None (or another suitable value) to mark that some
variable has no meaningful content right now.

that is, instead of

write

variable = None

if condition:
variable = 1

...

if variable is None:
print "variable not set"

</F>


Hi Fredrik and all,

I'm a hobbyist and still learning, but the claim the try/except is
"lousy Python" surprise me a bit. The try/except way seems like an
instance of "Easier to ask Forgiveness than Permission", and my sense
is that in 95% of cases that approach is widely considered more
Pythonic than LBYL (of which the suggested idiom seems reminiscent).

As it happens, most of my code does preset names to None, but reading
this thread made me wonder. Are you suggesting setting to None is
better as it makes explicit that there is nothing there, but this may
change in the future? (This is why I do it.) Or for some other reason?

I have no partisan interests either way; I'm just trying to
understand. Thanks and best,

Brian vdB
 
S

Steven Bethard

Brian said:
Fredrik Lundh said unto the world upon 2005-04-11 10:14:


I'm a hobbyist and still learning, but the claim the try/except is
"lousy Python" surprise me a bit. The try/except way seems like an
instance of "Easier to ask Forgiveness than Permission", and my sense
is that in 95% of cases that approach is widely considered more Pythonic
than LBYL (of which the suggested idiom seems reminiscent).

As it happens, most of my code does preset names to None, but reading
this thread made me wonder. Are you suggesting setting to None is
better as it makes explicit that there is nothing there, but this may
change in the future? (This is why I do it.) Or for some other reason?

I had a similar reaction to Fredrik's statement. In general, I wouldn't
call a try/except solution lousy style, as long as the path through
except was sufficiently "exceptional". That is, for code like:

if condition_that_happens_99_percent_of_the_time:
variable = 1
try:
variable
except NameError:
print "variable not set"

seems perfectly reasonable to me, because the exception is caught in the
*exceptional* case. However, if one case isn't clearly the exceptional
one, then it probably doesn't makes sense to use an exception, and I'd
write it like:

variable = None
if condition_that_happens_40_percent_of_the_time:
variable = 1
...
if variable is None:
print "variable not set"

Actually, I typically refactor my code so that I can write situations
like this as:

if condition_that_happens_40_percent_of_the_time:
variable = 1
...
else:
print "variable not set"

But the point still stands. If the variable being unset really is an
exceptional case, use an exception. If it's not, then an if/else block
is probably the better way to go.

STeVe
 
R

Richard Brodie

I'm a hobbyist and still learning, but the claim the try/except is
"lousy Python" surprise me a bit.

I think it wasn't the use of try/except as such. It's more that
if you're the developer you ought to know whether variables
are defined or not. It might be a sign you're using global
variables more often than would be considered good style in
Python.
 
B

Brian van den Broek

Richard Brodie said unto the world upon 2005-04-12 04:56:
I think it wasn't the use of try/except as such. It's more that
if you're the developer you ought to know whether variables
are defined or not. It might be a sign you're using global
variables more often than would be considered good style in
Python.

Richard and STeVe,

thanks for the replies :)

I see your point, Richard. Though where it has come up for me most
often is code internal to a class, where I only need a "real" value
for a class attribute in some cases, depending upon the inputs to the
class __init__. "Globals are bad" is one lesson I have learned :)

STeVe stressed that the try/except solution is only really appropriate
for cases where the failure to have the variable defined is quite
rare. Even though wary of "the root of all evil ... " that seems a
good reminder. Thanks.

Best to all,

Brian vdB
 
S

Scott David Daniels

Brian said:
... STeVe stressed that the try/except solution is only really appropriate
for cases where the failure to have the variable defined is quite rare.

Beware: C++ and Java have an immense overhead for exceptions. Python
has a very lightweight exception mechanism. You should _very_seldom_
choose exceptions or not on the basis of performance without measuring
the actual use; you are sure to be surprised.

Structure your code to be easiest to understand. _If_ it is too slow,
investigate ways to improve its performance. The usual way is to
build better data structures and use better algorithms. Only in the
core of a frequently used inner loop should you even care about the
cost of exceptions. Even then, you can often lift the exception
handler around the loop and recover the most necessary performance.

--Scott David Daniels
(e-mail address removed)
 
F

Fredrik Lundh

Scott said:
appropriate


Beware: C++ and Java have an immense overhead for exceptions. Python
has a very lightweight exception mechanism. You should _very_seldom_
choose exceptions or not on the basis of performance without measuring
the actual use; you are sure to be surprised.

Structure your code to be easiest to understand. _If_ it is too slow,
investigate ways to improve its performance. The usual way is to
build better data structures and use better algorithms. Only in the
core of a frequently used inner loop should you even care about the
cost of exceptions.

you haven't really read this thread, have you?

</F>
 
S

Steven Bethard

Scott said:
Beware: C++ and Java have an immense overhead for exceptions. Python
has a very lightweight exception mechanism. You should _very_seldom_
choose exceptions or not on the basis of performance without measuring
the actual use; you are sure to be surprised.

I'll just point out that I wasn't suggesting that try/except should be
used as an optimization, but that it should be used when *exceptional*
behavior is encountered. Using try/except for non-exceptional behavior
can be confusing for readers of your code who assume the normal
semantics. Just to make sure my point is clear, a great case for
try/except is with dictionaries, e.g.
try:
v = d[k]
except KeyError:
...
In this case, the key not being in the dictionary clearly makes sense as
exceptional behavior because there's no reason to have a dictionary if
there's nothing in it. Similarly, try/excepts are great for dealing
with duck typing issues, e.g.:
def f(mapping)
try:
itervalues = mapping.itervalues
except AttributeError:
values = (mapping[k] for k in mapping)
else:
values = itervalues()
...
Again, the point is that the AttributeError is the *exceptional*
behavior; f expects a mapping with an itervalues method, and if it
receives an object that doesn't have one, it has to deal with the
exceptional case of replacing that method.

Anyway, I hope that clarifies my intentions. Use try/except when it
makes sense to talk about something as being *exceptional* behavior. If
it doesn't, you should probably use if/else.

STeVe

P.S. That said, there *are* performance differences. Here's a test that
shows how try/except can be more costly the more often the except clause
is reached:

----------------------------------------------------------------------
import timeit

def ifelse(mapping, key):
if key in mapping:
return mapping[key]
else:
return None

def tryexcept(mapping, key):
try:
return mapping[key]
except KeyError:
return None

setup_code = """\
from __main__ import %s as func
mapping = %s
keys = %s
"""

test_code = '[func(mapping, key) for key in keys]'

def get_time(func, mapping, keys):
return timeit.Timer(test_code, setup_code % (
func.__name__, mapping, keys)).timeit(1000)

if __name__ == '__main__':
N = 1000
mapping = dict((i, i**2) for i in xrange(N))
for i in [0, 1, 2, 4, 8]:
number_missing = i*N/100
keys = range(number_missing, N + number_missing)
ifelse_time, tryexcept_time = (get_time(func, mapping, keys)
for func in [ifelse, tryexcept])
result = ['%3i%%' % (100*number_missing/N)]
for time, func in sorted([(ifelse_time, ifelse),
(tryexcept_time, tryexcept)]):
result.extend(['%.4f' % time, '%10s' % func.__name__])
print '\t'.join(result)
----------------------------------------------------------------------

And the results I get from running it:

[D:\Steve]$ test.py
0% 0.8467 tryexcept 0.9415 ifelse
1% 0.9374 tryexcept 0.9430 ifelse
2% 0.9499 ifelse 1.0375 tryexcept
4% 0.9580 ifelse 1.1576 tryexcept
8% 0.9333 ifelse 1.4187 tryexcept

Thus try/except is better when almost all of the keys can be found in
the dict, but as soon as even 2% of the keys cannot, if/else is the more
efficient solution. This is toy data, so obviously YMMV. But if you
use try/except for a very frequent occurrence instead of an exceptional
one, you may notice a performance hit.
 
M

Michael J. Fromberger

how testing if a variable exists in python as isset in php??

Would the following be a satisfactory implementation?

def isset(varname, lloc = locals()):
return varname in lloc or varname in globals()

I believe this works as desired:
... z = 10
... print isset('z') ## ==> True
... print isset('y') ## ==> True
... print isset('x') ## ==> True
...

Tests:
Perhaps this is not the most elegant solution, but I believe it handles
scoping correctly.

-M
 
P

Peter Otten

Michael said:
Would the following be a satisfactory implementation?

def isset(varname, lloc = locals()):
return varname in lloc or varname in globals()

I believe this works as desired:

... z = 10
... print isset('z') ## ==> True
... print isset('y') ## ==> True
... print isset('x') ## ==> True
...

Tests:

No, try it again in a fresh interpreter:
.... return name in loc or name in globals()
........ z = 10
.... print isset("x"), isset("y"), isset("z")
....
It may seem from the above that at least the global variable "x" is found
correctly, but beware, the global namespace where isset() is defined is
searched, not the one where it is called. Untested:

def isset(name):
frame = sys._getframe(1)
return name in frame.f_locals or name in frame.f_globals

might work, but is too magic for my taste.

Peter
 

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
474,234
Messages
2,571,180
Members
47,813
Latest member
RustyGary3

Latest Threads

Top