Search code examples
pythonpython-3.xmetaprogrammingdescriptor

Python: how does descriptors disguise object`s attributes and how does it work?


Hello everyone! I have got one problem: I don't completly understand how does descriptor "sets" a attribute.I wrote my guesses in the code, if they are not correct, can you say me the right variant?Thanks in advance!

class Descriptor:
    _counter = 0

    def __init__(self):
        self.attr_name = f'Descriptor attr#{Descriptor._counter}'
        Descriptor._counter += 1

    def __get__(self, instance, owner):
        return self if instance is None else instance.__dict__[self.attr_name]

    def __set__(self, instance, value):
        if value > 0:
            instance.__dict__[self.attr_name] = value
        else:
            msg = 'Value must be > 0!'
            raise AttributeError(msg)

class Shop():
    weight = Descriptor()
    price = Descriptor()


    def __init__(self, name, price, weight):
        self.name = name
        self.price = price  # Descriptor.__set__(price, self, price)
        self.weight = weight  # Descriptor.__set__(weight, self, weight)
        # Is it correct?

    def __repr__(self):
        return f'{self.name}: price - {self.price} weight - {self.weight}'

    def buy(self):
        return self.price * self.weight

Solution

  • Essentially yes, although your guess Descriptor.__set__(price, self, price) mentions price twice so I'm guessing what you mean. To be precise, it runs this:

    Descriptor.__set__(type(self).__dict__["price"], self, price)