Contrary to other answers already posted you cannot modify locals() directly and expect it to work.
>>> def foo():
lcl = locals()
lcl['xyz'] = 42
print(xyz)
>>> foo()
Traceback (most recent call last):
File "<pyshell#6>", line 1, in <module>
foo()
File "<pyshell#5>", line 4, in foo
print(xyz)
NameError: global name 'xyz' is not defined
Modifying locals() is undefined. Outside a function when locals() and globals() are the same it will work; inside a function it will usually not work.
Use a dictionary, or set an attribute on an object:
d = {}
d['xyz'] = 42
print(d['xyz'])
or if you prefer, use a class:
class C: pass
obj = C()
setattr(obj, 'xyz', 42)
print(obj.xyz)
Edit:
Access to variables in namespaces that aren't functions (so modules, class definitions, instances) are usually done by dictionary lookups (as Sven points out in the comments there are exceptions, for example classes that define __slots__). Function locals can be optimised for speed because the compiler (usually) knows all the names in advance, so there isn't a dictionary until you call locals().
In the C implementation of Python locals() (called from inside a function) creates an ordinary dictionary initialised from the current values of the local variables. Within each function any number of calls to locals() will return the same dictionary, but every call to locals() will update it with the current values of the local variables. This can give the impression that assignment to elements of the dictionary are ignored (I originally wrote that this was the case). Modifications to existing keys within the dictionary returned from locals() therefore only last until the next call to locals() in the same scope.
In IronPython things work a bit differently. Any function that calls locals() inside it uses a dictionary for its local variables so assignments to local variables change the dictionary and assignments to the dictionary change the variables BUT that's only if you explicitly call locals() under that name. If you bind a different name to the locals function in IronPython then calling it gives you the local variables for the scope where the name was bound and there's no way to access the function locals through it:
>>> def foo():
... abc = 123
... lcl = zzz()
... lcl['abc'] = 456
... deF = 789
... print(abc)
... print(zzz())
... print(lcl)
...
>>> zzz =locals
>>> foo()
123
{'__doc__': None, '__builtins__': <module '__builtin__' (built-in)>, 'zzz': <built-in function locals>, 'foo': <function foo at 0x000000000000002B>, '__name__': '__main__', 'abc': 456}
{'__doc__': None, '__builtins__': <module '__builtin__' (built-in)>, 'zzz': <built-in function locals>, 'foo': <function foo at 0x000000000000002B>, '__name__': '__main__', 'abc': 456}
>>>
This could all change at any time. The only thing guaranteed is that you cannot depend on the results of assigning to the dictionary returned by locals().
Contrary to other answers already posted you cannot modify locals() directly and expect it to work.
>>> def foo():
lcl = locals()
lcl['xyz'] = 42
print(xyz)
>>> foo()
Traceback (most recent call last):
File "<pyshell#6>", line 1, in <module>
foo()
File "<pyshell#5>", line 4, in foo
print(xyz)
NameError: global name 'xyz' is not defined
Modifying locals() is undefined. Outside a function when locals() and globals() are the same it will work; inside a function it will usually not work.
Use a dictionary, or set an attribute on an object:
d = {}
d['xyz'] = 42
print(d['xyz'])
or if you prefer, use a class:
class C: pass
obj = C()
setattr(obj, 'xyz', 42)
print(obj.xyz)
Edit:
Access to variables in namespaces that aren't functions (so modules, class definitions, instances) are usually done by dictionary lookups (as Sven points out in the comments there are exceptions, for example classes that define __slots__). Function locals can be optimised for speed because the compiler (usually) knows all the names in advance, so there isn't a dictionary until you call locals().
In the C implementation of Python locals() (called from inside a function) creates an ordinary dictionary initialised from the current values of the local variables. Within each function any number of calls to locals() will return the same dictionary, but every call to locals() will update it with the current values of the local variables. This can give the impression that assignment to elements of the dictionary are ignored (I originally wrote that this was the case). Modifications to existing keys within the dictionary returned from locals() therefore only last until the next call to locals() in the same scope.
In IronPython things work a bit differently. Any function that calls locals() inside it uses a dictionary for its local variables so assignments to local variables change the dictionary and assignments to the dictionary change the variables BUT that's only if you explicitly call locals() under that name. If you bind a different name to the locals function in IronPython then calling it gives you the local variables for the scope where the name was bound and there's no way to access the function locals through it:
>>> def foo():
... abc = 123
... lcl = zzz()
... lcl['abc'] = 456
... deF = 789
... print(abc)
... print(zzz())
... print(lcl)
...
>>> zzz =locals
>>> foo()
123
{'__doc__': None, '__builtins__': <module '__builtin__' (built-in)>, 'zzz': <built-in function locals>, 'foo': <function foo at 0x000000000000002B>, '__name__': '__main__', 'abc': 456}
{'__doc__': None, '__builtins__': <module '__builtin__' (built-in)>, 'zzz': <built-in function locals>, 'foo': <function foo at 0x000000000000002B>, '__name__': '__main__', 'abc': 456}
>>>
This could all change at any time. The only thing guaranteed is that you cannot depend on the results of assigning to the dictionary returned by locals().
Others have suggested assigning to locals(). This won't work inside a function, where locals are accessed using the LOAD_FAST opcode, unless you have an exec statement somewhere in the function. To support this statement, which could create new variables that are not known at compile time, Python is then forced to access local variables by name within the function, so writing to locals() works. The exec can be out of the code path that is executed.
def func(varname):
locals()[varname] = 42
return answer # only works if we passed in "answer" for varname
exec "" # never executed
func("answer")
>>> 42
Note: This only works in Python 2.x. They did away with this foolishness in Python 3, and other implementations (Jython, IronPython, etc.) may not support it either.
This is a bad idea, though. How will you access the variables if you don't know their name? By locals()[xxx] probably. So why not just use your own dictionary rather than polluting locals() (and taking the chance of overwriting a variable your function actually needs)?
Unless there is an overwhelming need to create a mess of variable names, I would just use a dictionary, where you can dynamically create the key names and associate a value to each.
a = {}
k = 0
while k < 10:
# dynamically create key
key = ...
# calculate value
value = ...
a[key] = value
k += 1
There are also some interesting data structures in the collections module that might be applicable.
globals() returns a dictionary of the module's variables. You can create a new variable by creating a key on that dictionary:
# By default, a module has some hidden variables defined
print({k: v for k, v in globals().items() if not k.startswith("__")})
for i in range(1, 11):
globals()[f"my_variable_{i}"] = i
print()
print(my_variable_1)
print(my_variable_2)
# and so on
print()
print({k: v for k, v in globals().items() if not k.startswith("__")})
Result:
{}
1
2
{'i': 10, 'my_variable_1': 1, 'my_variable_2': 2, 'my_variable_3': 3, 'my_variable_4': 4, 'my_variable_5': 5, 'my_variable_6': 6, 'my_variable_7': 7, 'my_variable_8': 8, 'my_variable_9': 9, 'my_variable_10': 10}
Videos
If you really want to do this, you could use exec:
print 'iWantAVariableWithThisName' in locals()
junkVar = 'iWantAVariableWithThisName'
exec(junkVar + " = 1")
print 'iWantAVariableWithThisName' in locals()
Of course, anyone will tell you how dangerous and hackish using exec is, but then so will be any implementation of this "trickery."
You can play games and update locals() manually, which will sometimes work, but you shouldn't. It's specifically warned against in the docs. If I had to do this, I'd probably use exec:
>>> 'iWantAVariableWithThisName' in locals()
False
>>> junkVar = 'iWantAVariableWithThisName'
>>> exec(junkVar + '= None')
>>> 'iWantAVariableWithThisName' in locals()
True
>>> print iWantAVariableWithThisName
None
But ninety-three times out of one hundred you really want to use a dictionary instead.
Use lists instead of this insanity called variable variables.
def build_ports(portlist)
ports = []
for idx, portname in enumerate(portlist):
ports.append(Port())
ports[-1].port_method1()
if idx > 5:
ports[-1].port_method2()
Instead of using ports[-1], you might instead scrap the unused portname iteration variable and create a local portname = Port(), use that to call the methods and then append it to ports at the end. What is portlist anyway?
No, this is not possible. If you look at how Python stores local variables, you can see why.
Global variables are stored in a hash table, which is dynamically-sized, and the names are compiled into hash keys (in Python parlance, interned strings). This makes global lookups comparatively "slow", but since one needs to find globals by name from other compilation units (modules), it's required:
# a.py
x = 3
# b.py
import a
a.x = 4 # b needs to know how to find the same x!
Local variables are stored in a fixed-size array and the names are compiled into array indices.
This can be seen when you look at the bytecode, which has LOAD_FAST and STORE_FAST for locals but LOAD_GLOBAL and STORE_GLOBAL for globals. It also leaks through in the different exceptions you get. Globals trickle up and generate a NameError when not found, but undefined locals are detected by an empty slot, giving an UnboundLocalError.
def foo():
a
a = 1
foo()
Traceback (most recent call last):
File "<stdin>", line 1, in foo
UnboundLocalError: local variable 'a' referenced before assignment
def foo():
a = 1
foo()
Traceback (most recent call last):
File "<stdin>", line 1, in foo
NameError: global name 'a' is not defined
Because the array is fixed-size, and the size is computed while compiling the function, you cannot create any additional locals.
If you need more "locals", you'll need to store the values as named attributes of an object or in a dictionary; obviously that will also negate the speed benefits.
"Each dynamic fget accessor needs a unique local variable."
That tells you that each "property" is a separate instance of some class.
Consider using descriptors for this so that you have a complete class instead of some cobbed-up instance variable.
Or consider using some variant on the Strategy design pattern to delegate this "unique local variable" to this property-related Strategy object.
One alternative is to define a second function that captures the value of the variable as a new local. E.g.:
def make_prop_that_returns(i):
return property(lambda self: i)
class Test(object):
def __metaclass__(name, bases, dict):
for i in range(5):
dict['f%d' % i] = make_prop_that_returns(i)
return type(name, bases, dict)
I'm not sure I'd say this is much cleaner than your approach, but it's an alternative at least.
Can you be more clear (less abstract) about what you're trying to accomplish? Defining dynamic fget's might not be the best way to do it.