Search code examples
python-2.7attributesdescriptorgetattrname-lookup

What is __getattr__ order in the attribute lookup chain?


So in order to get rid of some boilerplate I opted to implement __getattr__ for delegating some method calls. The problem is that I also have a descriptor in the attribute lookup chain and they are not interacting as I expected. Here's the code:

class C(object):
    attr = Descriptor()

    def __getattr__(self, item):
        # just returns a method for all items that match
        # a certain pattern

Here's the problem. All the Python docs mention that __getattr__ only gets called after the usual lookup chain fails but in this case __getattr__ is always getting called ahead of attr.

So what is the proper way to have both a descriptor and __getattr__ play nice with each other?

Here's what I'm observing:

a = C()
a.attr # goes to __getattr__ instead of C.attr.__get__

Issue solved. It turns out if there is an exception that is thrown from a descriptor then the lookup jumps to __getattr__.


Solution

  • but in this case __getattr__ is always getting called ahead of attr

    Sorry, I do not understand.

    >>> class C(object):
        attr = property(fget = lambda self: 5)
    
        def __getattr__(self, item):
            # just returns a method for all items that match
            # a certain pattern
    
        return item
    
    >>> C().x
    'x'
    >>> C().attr # attr.__get__ is called, not __getattr__
    5
    

    Could you specify what 'play nice with each other' means? A way to play nicely as I understand it: Method delegation in python