79255013

Date: 2024-12-05 14:10:57
Score: 0.5
Natty:
Report link

I am going to borrow Marty Alchin's answer:

... the fact that only __get__ can receive the owner class, while the rest only receive the instance.

Descriptors are assigned to a class, not to an instance, and modifying the class would actually overwrite or delete the descriptor itself, rather than triggering its code. This is intentional. Otherwise, once a descriptor is set, it could never be removed or modified without modifying source code and restarting the program. That’s not preferable, so only the retrieval method (__get__) has access to the owner class.

An example to show what is explained above. The code also explains this portion of @Gery Ogam's answer:

import random

class Die:
    def __init__(self, sides=6):
        self.sides = sides

    def __get__(self, instance, owner=None):
        return int(random.random() * self.sides) + 1

    def __set__(self, instance, value):
        ...

class Game:
    d6 = Die()

# Assume:
# if `__set__` was designed to take an `owner` class,
# the code below will trigger the `__set__` method
# rather than call `__get__` to override
# the value of `d6` in the `Game.__dict__`.
Game.d6 = 3
print(Game.d6)  # 3

The owner will always be set to the appropriate class, though instance may be None if the attribute was accessed from the class. This is what Django uses to throw an error if you try to access a manager from an object instead of a class, or a related model (ForeignKey) on a class instead of an object.

Reasons:
  • Long answer (-1):
  • Has code block (-0.5):
  • User mentioned (1): @Gery
  • Low reputation (1):
Posted by: Bazzan