Search code examples
pythongetattr

Python getattr from locals() fails with AttributeError


Hopefully this is not the late-night effect, but I'm stumped by a very simple problem:

def test_getattr(v0):
    v1 = "test1"
    v2 = "test2"
    v3 = "test3"

    for k, v in locals().items():
        print(k, v)

    print(getattr(locals(), 'v1'))

test_getattr("test0")

The output gives the locals() dict items as expected:

v0 test0
v3 test3
v1 test1
v2 test2

But then dies with:

AttributeError: 'dict' object has no attribute 'v1'

v1 clearly is in the locals() 'dict', per the initial output, but then getattr() insists otherwise.

This is my first need to use locals(), but every bit of documentation I can find suggests this should work. What am I missing?

Edit/Update: Many thanks to @martijn for answer below. I managed to use dynamic local variables in getattr() by transiently assigning the local variables to a dummy class:

class Attr:
    pass

def test_getattr(v0):
    A = Attr()
    A.v1 = "test1"
    #etc

    print(getattr(A, "v1"))

Solution

  • getattr() retrieves attributes, not dictionary keys, and dictionary keys are not attributes. locals() is just another dictionary, so use it as one:

    print(locals()['v1'])
    

    You'll otherwise only find the normal dictionary attributes on locals(), such as keys and items and __len__ and __getitem__:

    >>> type(locals())
    <type 'dict'>
    >>> dir(locals())
    ['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values', 'viewitems', 'viewkeys', 'viewvalues']
    >>> getattr(locals(), 'keys')
    <built-in method keys of dict object at 0x10028f168>