I would like to add an attribute that uses the descriptor protocol to an instance of a class at construction-time. It's certainly possible to add such an attribute to a class, but sometimes it would be convenient to be able to instantiate the descriptor-protocol-implementing object with some context from the class instance.
I have been lead to believe that this is possible by the following test in the Python Descriptor HowTo:
The default behavior for attribute access is to get, set, or delete the attribute from an object’s dictionary. For instance,
a.xhas a lookup chain starting witha.__dict__['x'], thentype(a).__dict__['x'], and continuing through the base classes oftype(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.
Here is a simple example of what I am trying to do:
class Desc:
def __init__(self, n):
self.n = n
def __get__(self, *args):
return f"Hello {self.n}!"
class Thing:
def __init__(self, n):
self.foo = Desc(n)
t = Thing("Dave")
print(t.foo)
This results in:
<__main__.Desc object at 0x7fcdb5ee9c50>
Whereas I was hoping for it to display "Hello Dave!".
I think that the line reading self.foo = Desc(n) is successfully adding the Desc instance to the Thing instance's __dict__, but Python is not invoking "the descriptor method instead" (as expected from the quoted documentation). What's going on, and how do I achieve the kind of thing I am looking to do?