-1

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"))
GoneAsync
  • 349
  • 5
  • 18

1 Answers1

5

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>
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Hmm. Thanks for that -- I *was* worried that 'keys' and 'attributes' weren't synonymous in usage even though they can be equivalently expressed in these forms with regular dicts. Unfortunately, what I need to do is dynamically build a SQLAlchemy query filter, with the tables are determined within the function as local variables. I'll ask that as a different question with different tags; I thought I'd reduced it to the minimal working example, but I clearly need to get very specific. Many thanks for your help. – GoneAsync May 16 '15 at 13:42
  • So you mean there is no way for using `getattr` on dictionaries? – Amir Hossein Baghernezad Aug 20 '17 at 10:20
  • @TechJS: you can use `getattr()` on dictionaries just fine, dictionaries have attributes *as well*. But attributes are not key-value pairs, that's what you use indexing for. – Martijn Pieters Aug 20 '17 at 15:36
  • @MartijnPieters Aha you mean for example, `key = 'some_key'` we can use `dictionary[key]` instead of directly using `dictionary['some_key']`. Thats equivalent. – Amir Hossein Baghernezad Aug 21 '17 at 08:04