2

I am trying to override getattr method and as per my understanding there should be infinite loop in the following code snippet as by default object.__getattribute__(self,attr) is invoked which will invoke overrided getattr method as attribute 'notpresent' is not present in namespaces and this process will be keep on repeating. Can anybody help me in figuring out that why this behavior is not observed here.

Moreover I am unable to figure out that why AttributeError is not raised when implicit call to getattribute is done while accessing attribute using dot notation while it is being raised second time when we are trying to invoke getattribute explicitly within method

class Test(object):

    #Act as a fallback and is invoked when getattribute is unable to find attribute

    def __getattr__(self,attr):

        print "getattr is called"
        return object.__getattribute__(self,attr) #AttributeError is raised

t=Test([1,2,3,4])

b = t.notpresent
Vinit89
  • 583
  • 1
  • 7
  • 31
  • possible duplicate of [Python: avoiding infinite loops in \_\_getattribute\_\_](http://stackoverflow.com/questions/13538324/python-avoiding-infinite-loops-in-getattribute) – 301_Moved_Permanently Jul 21 '15 at 08:53

2 Answers2

4

You are calling object.__getattribute__ within Test.__getattr__.

There is no loop involved here.

Moreover, as per the docs, __getattribute__ does not implicitly call __getattr__.

Update after your edit

Here is the C-implementation of the __getattribute__ call. Especially the slot_tp_getattr_hook part.

In your case, the attribute lookup failure lead to the execution of line 6072 that calls your custom __getattr__ function.

From there on, the AttributeError has been cleared. But your call to object.__getattribute__ will set it back and line 6074 or 6075 won't handle it.

The object.__getattribute__ call is implemented like so and thus (re)raise AttributeError (line 1107).

301_Moved_Permanently
  • 4,007
  • 14
  • 28
  • As per docs overrided getattr should be called if AttributeError is raised – Vinit89 Jul 21 '15 at 09:10
  • `AttributeError` has already been handled, because `Test.__getattr__` is being called. Thus explicitly calling `object.__getattribute__` is exactly the same as calling it from `Test.__getattribute__` to avoid infinite loops. – 301_Moved_Permanently Jul 21 '15 at 09:25
0

Because the __getattribute__ normally only looks up the attribute in the __dict__ of the object and similar places - it does not implicitely call __getattr__ to retrieve the attribute.

Note that if __getattribute__ would call __getattr__ the __getattr__ method might be called twice if __getattribute__ failed to find the attribute (since lookup is supposed to call __getattr__ when __getattribute__ fails).

skyking
  • 13,817
  • 1
  • 35
  • 57
  • @brunodesthuilliers Perhaps, but just commenting "Sorry but plain wrong" does not help. Could you explain in what way my answer is wrong? – skyking Jul 21 '15 at 11:03
  • `__getattribute__` does not "normally only looks up the attribute in the `__dict__` of the object." - it handles the whole attribute lookup, including descriptors (computed attributes), looking up the instance's dicts OR slots, and looking up the class and parents classes. – bruno desthuilliers Jul 21 '15 at 11:07