0

The Python docs, specify that attribute access is done via the objects __dict__ attribute.

The default behavior for attribute access is to get, set, or delete the attribute from an object’s dictionary. For instance, a.x has a lookup chain starting with a.__dict__['x'], then type(a).__dict__['x'], and continuing through the base classes of type(a) excluding metaclasses. If the looked-up value is an object defining one of the descriptor methods, then Python may override the default behavior and invoke the descriptor method instead. Where this occurs in the precedence chain depends on which descriptor methods were defined.

In this example, I override the object's __dict__, but python can still manage to get its attribute, how does that work?:

In [1]: class Foo:
   ...:     def __init__(self):
   ...:         self.a = 5
   ...:         self.b = 3
   ...:     def __dict__(self):
   ...:         return 'asdasd'
   ...:

In [2]: obj_foo = Foo()

In [3]: obj_foo.__dict__
Out[3]: <bound method Foo.__dict__ of <__main__.Foo object at 0x111056850>>

In [4]: obj_foo.__dict__()
Out[4]: 'asdasd'

In [5]: obj_foo.b
Out[5]: 3
Ron Serruya
  • 3,988
  • 1
  • 16
  • 26

1 Answers1

-1

You are implementing the __dict__ method.

If you override the __dict__ attribute you will succeed in breaking Python:

class Foo:
    def __init__(self):
        self.a = 1
        self.__dict__ = {}

Foo().a
AttributeError: 'Foo' object has no attribute 'a'

Interestingly enough, if both are overridden everything is back to normal:

class Foo:
    def __init__(self):
        self.a = 1
        self.__dict__ = {}

    def __dict__(self):
        pass

print(Foo().a)

Outputs

 1

Making __dict__ a property also does not seem to break anything:

class Foo:
    def __init__(self):
        self.a = 1

    @property
    def __dict__(self):
        return {}

print(Foo().a)

Also outputs 1.


I suspect the answer to the question *why* lies (probably) deep in the CPython implementation of `object`, more digging needs to be done.
DeepSpace
  • 78,697
  • 11
  • 109
  • 154
  • I don't have time to really go through it now, but https://stackoverflow.com/questions/4877290/what-is-the-dict-dict-attribute-of-a-python-class might be interesting. – Thierry Lathuille Dec 29 '19 at 12:33
  • @ThierryLathuille that seem to talk about accessing an instance `__dict__` attribute through its class `__dict__` attribute, not why `instance.__dict__` sometimes breaks and sometimes no – DeepSpace Dec 29 '19 at 12:43