0

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

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?

Rob Gilton
  • 289
  • 1
  • 14
  • The descriptor protocol won't be invoked if it belongs to the instance – juanpa.arrivillaga Aug 13 '19 at 20:38
  • Is that not contrary to the bit of documentation I have quoted? – Rob Gilton Aug 13 '19 at 20:39
  • It seems ambiguous, but it's definitely documented somewhere, maybe not in the HOW TO. In any case, `__get__` is passed the instance as it's second argument, which is how this is handled – juanpa.arrivillaga Aug 13 '19 at 20:45
  • 1
    [Here is the documentation that makes this clear](https://docs.python.org/3/reference/datamodel.html#implementing-descriptors). "The following methods only apply when an instance of the class containing the method (a so-called descriptor class) appears in an owner class (the descriptor must be in either the owner’s class dictionary or in the class dictionary for one of its parents)." – juanpa.arrivillaga Aug 13 '19 at 21:16

0 Answers0