Data Model

Descriptors

Descriptors customize attribute access through __get__, __set__, or __delete__.

A descriptor object lives on the class. __set_name__ lets it learn which managed attribute it is serving.

Source

class Positive:
    def __set_name__(self, owner, name):
        self.private_name = "_" + name

    def __get__(self, obj, owner):
        if obj is None:
            return self
        return getattr(obj, self.private_name)

    def __set__(self, obj, value):
        if value <= 0:
            raise ValueError("must be positive")
        setattr(obj, self.private_name, value)

class Product:
    price = Positive()

print(Product.price.private_name)

Output

_price
obj.attrDESCRIPTOR__get____set____delete__
Attribute access on an instance routes through the descriptor's __get__/__set__/__delete__ when the attribute is a descriptor.

Assigning item.price calls Positive.__set__, and reading it calls Positive.__get__.

Source

class Product:
    price = Positive()

    def __init__(self, price):
        self.price = price

item = Product(10)
print(item.price)
try:
    item.price = -1
except ValueError as error:
    print(error)

Output

10
must be positive

Notes

See also

Run the complete example

Example code

Expected output

10
_price
must be positive

Execution time appears here after you run the example.