Search code examples
pythonlistclassdictionaryhasattr

Python's hasattr on list values of dictionaries always returns false?


I have a dictionary that sometimes receives calls for non-existent keys, so I try and use hasattr and getattr to handle these cases:

key_string = 'foo'
print "current info:", info
print hasattr(info, key_string)
print getattr(info, key_string, [])
if hasattr(info, key_string):
    array = getattr(info, key_string, [])
array.append(integer)
info[key_string] = array
print "current info:", info

The first time this runs with integer = 1:

current info: {}
False
[]
current info: {'foo': [1]}

Running this code again with integer = 2:

instance.add_to_info("foo", 2)

current info: {'foo': [1]}
False
[]
current info: {'foo': [2]}

The first run is clearly successful ({'foo': [1]}), but hasattr returns false and getattr uses the default blank array the second time around, losing the value of 1 in the process! Why is this?


Solution

  • hasattr does not test for members of a dictionary. Use the in operator instead, or the .has_key method:

    >>> example = dict(foo='bar')
    >>> 'foo' in example
    True
    >>> example.has_key('foo')
    True
    >>> 'baz' in example
    False
    

    But note that dict.has_key() has been deprecated, is recommended against by the PEP 8 style guide and has been removed altogether in Python 3.

    Incidentally, you'll run into problems by using a mutable class variable:

    >>> class example(object):
    ...     foo = dict()
    ...
    >>> A = example()
    >>> B = example()
    >>> A.foo['bar'] = 'baz'
    >>> B.foo
    {'bar': 'baz'}
    

    Initialize it in your __init__ instead:

    class State(object):
        info = None
    
        def __init__(self):
            self.info = {}