MRAB <pyt...@mrabarnett.plus.com> writes: > 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)
Note that "exec" can be used: >>> def init(name): ... return "init " + name ... >>> def foo(): ... for name in "bar", "baz": ... exec "%s = init(name)" % name ... print bar ... print baz ... >>> foo() init bar init baz Not that I can think of a reason to do this :) -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list