On 30/09/2010 18:07, kj wrote:



This is a recurrent situation: I want to initialize a whole bunch
of local variables in a uniform way, but after initialization, I
need to do different things with the various variables.

What I end up doing is using a dict:

d = dict()
for v in ('spam', 'ham', 'eggs'):
     d[v] = init(v)

foo(d['spam'])
bar(d['ham'])
baz(d['eggs'])



This is fine, but I'd like to get rid of the tedium of typing all
those extra d['...']s.

I.e., what I would *like* to do is something closer to this:

d = locals()
for v in ('spam', 'ham', 'eggs'):
     d[v] = init(v)

foo(spam)
bar(ham)
baz(eggs)

...but this results in errors like "NameError: global name 'spam' is
not defined".

But the problem is deeper than the fact that the error above would
suggest, because even this fails:

spam = ham = eggs = None
d = locals()
for v in ('spam', 'ham', 'eggs'):
     d[v] = init(v)

foo(spam) # calls foo(None)
bar(ham)  # calls bar(None)
baz(eggs) # calls baz(None)


In other words, setting the value of locals()['x'] does not set
the value of the local variable x.

I also tried a hack using eval:

for v in ('spam', 'ham', 'eggs'):
     eval "%s = init('%s')" % (v, v)

but the "=" sign in the eval string resulted in a "SyntaxError:
invalid syntax".

Is there any way to use a loop to set a whole bunch of local
variables (and later refer to these variables by their individual
names)?

The handling of local variables in CPython is optimised, so changing
locals() won't have any effect, as you discovered.

An alternative is to create a namespace in an instance of a class and
then add attributes to it:

class Namespace(object):
    pass

n = Namespace()
for v in ('spam', 'ham', 'eggs'):
    setattr(n, v, init(v))

foo(n.spam)
bar(n.ham)
baz(n.eggs)
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to