1

I want to redefine an object's get function so that I can intercept when any attribute is requested. Using the getattr function, it doesn't catch when existing variables (eg. attr1 in this case) are requested. Is there a way around this, so I can run a function when attr1 is requested?

class Test(object):
    attr1 = 1
    def __init__(self):
        self.attr2 = 1
    def __getattr__(self, attr):
        print 'GETATTR', attr
a = Test()
a.attr1
a.attr2
a.attr3

Output:

GETATTR attr3

I'd like to see GETATTR attr1 and GETATTR attr2 in the output too.

ninhenzo64
  • 702
  • 1
  • 9
  • 23
  • If you want to run code when your objects' attributes are accessed you might like [properties](http://stackoverflow.com/questions/6618002/python-property-versus-getters-and-setters), although class-level properties require [some extra code](http://stackoverflow.com/questions/31927444/is-there-a-function-like-getattr-that-gets-called-for-class-variables) – kuzzooroo Aug 10 '15 at 19:30

1 Answers1

3

It's not a matter of class or instance variables. It's a matter of whether the attribute exists or not; your attr1 exists but the others do not. (What you do with attr2 does not create an attribute; you're just creating a local variable and throwing it away. If you do self.attr2 = 1, you will see that __getattr__ is not called for attr2 either.)

As documented, __getattr__ is called "when an attribute lookup has not found the attribute in the usual places (i.e. it is not an instance attribute nor is it found in the class tree for self)". As also documented in the same place, there is another magic method __getattribute__ which is always called, even when the attribute does exist.

BrenBarn
  • 242,874
  • 37
  • 412
  • 384