namespace hacking question

Arnaud Delobelle arnodel at gmail.com
Thu Sep 30 14:41:59 EDT 2010


MRAB <python at 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


More information about the Python-list mailing list

AltStyle によって変換されたページ (->オリジナル) /