0

This is my code:

class myclass:
    def __init__(self):
        self.value = 5

    def __getattr__(self, attrname):
        if attrname == 'value':
            return 10

X = myclass()
print X.value

I suppose the output value should be 10 (__getattr__ modifies returned value). However output is 5.

If I remove initialization of value:

class myclass:

    def __getattr__(self, attrname):
        if attrname == 'value':
            return 10

X = myclass()
print X.value

It works as expected (returns 10). Why?

Hash Doe
  • 313
  • 2
  • 7

1 Answers1

2

__getattr__ is only used for missing attributes. See the documentation:

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).

In your first example, 'value' is not a missing attribute; it was set in __init__. Note that it doesn't matter where it was set, only that it exists.

If you must intercept all attribute access, you need to implement the __getattribute__ hook instead.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • But __setattr__ works for missing and not-missing attributes, right? – Hash Doe Jul 31 '17 at 09:22
  • 1
    @HashDoe: yes, because setting an attribute would *add* that attribute if it was missing. – Martijn Pieters Jul 31 '17 at 09:22
  • 1
    @HashDoe Also in 3.X for builtin accesses only `__getattr__` and `__getattribute__` are not intercepted this matters for proxy classes when they proxy other objects and expect their operator overloading methods to be called. – GIZ Jul 31 '17 at 09:30
  • 1
    @direprobs: you mean special methods perhaps? Yes, `__getattribute__` will be bypassed for some of those, but that's not specific to Python 3, that's the same in Python 2. See [*Special method lookup*](https://docs.python.org/3/reference/datamodel.html#special-method-lookup). – Martijn Pieters Jul 31 '17 at 09:32
  • 1
    @MartijnPieters Yes, that's what I meant. Yup, you're right it's not just in 3.X but for new-style classes in both lines 2.X & 3.X. – GIZ Jul 31 '17 at 09:40