Saturday, April 28, 2012

Hidden methods in Python

How would one access variables programmatically in Python? Well, there are two dictionaries, one returned by globals() which contains all global variables, and one returned by locals() which contains all local variables. To demonstrate:
>>> a = 4
>>> locals()['a']
4
>>> locals()['b'] = 'spam'
>>> b
'spam'
>>>
Declaring a variable is the same thing as accessing its name in the locals() dictionary (or the globals() dictionary if the variable is declared global).
But what if we do this:
class a:
    b = 4
locals()['a.b'] = 'spam'
What will be the value of a.b?



>>> a.b
4
>>>
The reason behind this is that the dot is not part of the variable name; you can't access a.b through locals()['a.b']. You'd have to do locals()['a'].b. But what about the value of 'spam' that we stored in there? It's still there:
>>> locals()['a.b']
'spam'
>>>
But we can't access it by just calling a.b. We couldn't even if there was no variable to begin with:

>>> del a
>>> a.b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> 
What happened here? It's simple: variable names with a dot in them are not permitted. So even though we have a variable called 'a.b' in locals(), it isn't accessible through the local namespace. The reason we were allowed to put it in locals(), though, is because locals() behaves like a regular Python dictionary. Dictionaries allow any string to be used as a key; we could even put a variable in there called 'class if ([{;\n@' and it would still accept it, it just wouldn't be accessible. Dictionaries actually allow any value to be used as a key, not just strings; we could say something like locals()[len] = 'spam' and it would work, because len is a built-in function which is a perfectly valid key.

Is there any use for hiding variables this way? Not really, because they're still accessible through locals(). But it offers an interesting look at the internals of Python variables.

No comments:

Post a Comment