namespace hacking question

MRAB python at mrabarnett.plus.com
Thu Sep 30 13:40:23 EDT 2010


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)



More information about the Python-list mailing list