Reputation: 36624
In S/O threads about iteratively creating variables, most replies suggest using globals()
, but highlight the fact that it is dangerous to play with the global scope.
Yet, locals()
and vars()
can also be used to iteratively create variables. For instance:
for i in range(1, 6):
vars()[f'variable_{i}'] = i
print(key for key in vars().keys() if 'variable' in key)
Out[2]: ['variable_1', 'variable_2', 'variable_3', 'variable_4', 'variable_5']
Are locals()
and vars()
safe to iteratively create variables? If so, why are they never mentioned, as opposed to globals()
?
Upvotes: 0
Views: 32
Reputation: 59701
Not, it is not safe to use vars
or locals
that way. From the documentation:
vars
:
Without an argument,
vars()
acts likelocals()
. Note, the locals dictionary is only useful for reads since updates to the locals dictionary are ignored.
Note: The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.
In the case of locals
, one could give that note the interpretation that you should not change the existing contents in the returned dictionary (as opposed to introducing new contents). Still, nothing in the documentation suggests that introducing new values in the dictionary should have any effect.
Upvotes: 1
Reputation: 531125
Assigning to the output of vars
doesn't actually modify the local scope; it just populates a mapping which you can only access via vars()
. Observer:
>>> def bar():
... for i in range(6):
... vars()[f'var_{i}'] = i
... print(vars()['var_3'])
... print(var_3)
...
>>> bar()
3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in bar
NameError: name 'var_3' is not defined
Since you are already commited to mapping semantics, you may as well just use a dict
:
def bar():
data = {}
for i in range(6):
data[f'var_{i}'] = i
print(data['var_3'])
Upvotes: 1