Search code examples
pythonpython-2.7getattr

Why is getattr() so much slower than self.__dict__.get()?


The example below is from a REST database driver on Python 2.7.

In the __setattr__ method below, if I use the commented out getattr() line, it reduces the object instantiation performance from 600 rps to 230.

Why is getattr() so much slower than self.__dict__.get() in this case?

class Element(object):

    def __init__(self, client):
        self._client = client
        self._data = {}
        self._initialized = True

    def __setattr__(self, key, value):
        #_initialized = getattr(self, "_initialized", False)
        _initialized = self.__dict__.get("_initialized", False)
        if key in self.__dict__ or _initialized is False:
            # set the attribute normally
            object.__setattr__(self, key, value)
        else:
            # set the attribute as a data property
            self._data[key] = value

Solution

  • In short: because getattr(foo,bar) does the same thing as foo.bar, which is not the same thing as just accessing the __dict__ property (for a start, getattr has to select the right __dict__, but there's a whole lot more going on).

    An example for illustration:

    >>> class A:
    ...   a = 1
    ...
    >>> class B(A):
    ...   b = 2
    ...
    >>> dir(B)
    ['__doc__', '__module__', 'a', 'b']
    >>> B.a
    1
    >>> B.__dict__
    {'__module__': '__main__', 'b': 2, '__doc__': None}
    >>> B.__dict__['a']
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    KeyError: 'a'
    >>> B.__dict__.get('a')
    >>>
    

    Details contained in, or linked to here: http://docs.python.org/reference/datamodel.html (search for "getattr").