0

i want the next code to work

class A(object):
    def __getattr__(self, item):
        print item
        return self.item
    def x(self):
        print 4
a = A()
a.x()

and the output will ber

x
4

i know its not working becuase x is like a static variable and not an instance variable. I saw this __getattr__ for static/class variables in python and it doesn't seem to work in my case how can it be done?

thx

Community
  • 1
  • 1
kill129
  • 100
  • 10
  • Possible duplicate of [How do I override \_\_getattr\_\_ in Python without breaking the default behavior?](http://stackoverflow.com/questions/2405590/how-do-i-override-getattr-in-python-without-breaking-the-default-behavior) – syntonym Jun 24 '16 at 11:55
  • its completly unrelated – kill129 Jun 24 '16 at 11:58
  • 1
    There's not much difference between methods and attributes in new-style classes. `__getattr__` only gets involved if the actual attribute cannot be found (and `x` **can** be found in this case). *"i want the next code to work"* - it **does work**, that's what's supposed to happen. – jonrsharpe Jun 24 '16 at 11:58
  • @kill129 No, it solves your question if you read the answer carefully. I quote: `__getattr__ is only called as a last resort i.e. if there are no attributes in the instance that match the name [...] However, unlike __getattr__, __getattribute__ will be called first` – syntonym Jun 24 '16 at 12:01
  • Possible duplicate of [Is there a function like \_\_getattr\_\_ that gets called for class variables?](http://stackoverflow.com/questions/31927444/is-there-a-function-like-getattr-that-gets-called-for-class-variables) – Tadhg McDonald-Jensen Jun 24 '16 at 18:05

1 Answers1

5

There are a couple of obvious problems with your code:

class A(object):

    def __getattr__(self, item):  # 1
        print item
        return self.item  # 2

    def x(self):  # 1 again
        print 4
  1. __getattr__ will only be invoked if item cannot be found the normal way. For item == 'x', therefore, it is never invoked.
  2. Which is probably just as well, since self.item looks for the attribute item, not the attribute corresponding to whatever is assigned to item. This doesn't exist, so would invoke __getattr__. If you try A().y() you'll get RuntimeError: maximum recursion depth exceeded while calling a Python object.

Instead, I think you want to use __getattribute__, which is always invoked. You need to be careful not to get the same runtime error, though; here I avoid it by calling the superclass implementation of __getattribute__, the naïve way of calling getattr(self, item) would fail:

class A(object):

    def __getattribute__(self, item):
        print item
        return super(A, self).__getattribute__(item)

    def x(self):
        print 4

Which gives:

>>> A().x()
x
4
>>> A().y()
y
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in __getattribute__
AttributeError: 'A' object has no attribute 'y'

Note that both __getattr__ and __getattribute__ apply equally to attributes and methods (which are, more or less, just callable attributes).

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437