Suppose
class D:
def __init__(self,id): self.id = id
def __get__(self,obj,type=None):
print(self.id,"__get__ is called")
class C:
d1 = D(1)
d2 = D(2)
d3 = D(3)
c = C()
then during the call hasattr(c,"d1")
the __get__
method of C.d1
is called. Why? Shouldn't hasattr()
just check the dictionaries?
The same (but weirder) happens when <tab>
is presses for completion in an interactive CPython-version-3.6.10-session, as in c.d<tab>
. In this case __get__
will be called for all matching attributes except the last one.
What is going on here?
If you look at the
help
forhasattr
(or the documentation:So no, it doesn't just "check dictionaries", it couldn't do that because not all objects have dictionaries as namespaces to begin with, e.g. built-in objects, or user-defined objects with
__slots__
.getattr(obj, name)
will correctly invoke the equivalent machinery as:Which would call the descriptor's
__get__