Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Lära __get__, __set__, __delete__ | What Descriptors Are
Python Descriptors Explained

__get__, __set__, __delete__

Svep för att visa menyn

A descriptor is any object that defines at least one of three special methods: __get__, __set__, or __delete__. When an instance of such an object is assigned as a class attribute, Python's attribute lookup machinery calls these methods automatically instead of returning the object directly.

The Three Methods

__get__(self, obj, objtype=None) is called when the attribute is read. obj is the instance accessing the attribute (None when accessed from the class). objtype is the class:

12345678910111213
# A minimal read-only descriptor class Descriptor: def __get__(self, obj, objtype=None): if obj is None: return self # Accessed from the class – return the descriptor itself return f"Value accessed on {obj.__class__.__name__}" class Report: status = Descriptor() # Descriptor assigned as a class attribute report = Report() print(report.status) # "Value accessed on Report" print(Report.status) # The Descriptor object itself

__set__(self, obj, value) is called when the attribute is written:

1234567891011121314151617181920212223242526
# A descriptor that validates and stores a value class PositiveNumber: def __set_name__(self, owner, name): self._name = name # Storing the attribute name for error messages def __get__(self, obj, objtype=None): if obj is None: return self return obj.__dict__.get(self._name) def __set__(self, obj, value): if not isinstance(value, (int, float)) or value <= 0: raise ValueError(f"{self._name} must be a positive number, got {value!r}") obj.__dict__[self._name] = value class Product: price = PositiveNumber() def __init__(self, name, price): self.name = name self.price = price # Triggers __set__ laptop = Product("ThinkPad", 1200.0) print(laptop.price) # 1200.0 laptop.price = -50 # Raises ValueError

__delete__(self, obj) is called when the attribute is deleted with del:

1234567891011121314151617181920212223242526272829
# Adding deletion support to the descriptor class PositiveNumber: def __set_name__(self, owner, name): self._name = name def __get__(self, obj, objtype=None): if obj is None: return self return obj.__dict__.get(self._name) def __set__(self, obj, value): if not isinstance(value, (int, float)) or value <= 0: raise ValueError(f"{self._name} must be a positive number, got {value!r}") obj.__dict__[self._name] = value def __delete__(self, obj): obj.__dict__.pop(self._name, None) print(f"{self._name} removed from {obj!r}") class Product: price = PositiveNumber() def __init__(self, name, price): self.name = name self.price = price laptop = Product("ThinkPad", 1200.0) del laptop.price # Triggers __delete__ print(laptop.__dict__) # {'name': 'ThinkPad'}

__set_name__

__set_name__(self, owner, name) is called automatically when the descriptor is assigned to a class attribute. It gives the descriptor access to its own attribute name without hardcoding it:

1234567891011121314151617
# __set_name__ receives the class and attribute name at class creation time class TrackedAttribute: def __set_name__(self, owner, name): print(f"Descriptor assigned to {owner.__name__}.{name}") self._name = name def __get__(self, obj, objtype=None): if obj is None: return self return obj.__dict__.get(self._name) def __set__(self, obj, value): obj.__dict__[self._name] = value class Invoice: amount = TrackedAttribute() # Prints: Descriptor assigned to Invoice.amount currency = TrackedAttribute() # Prints: Descriptor assigned to Invoice.currency
question mark

What does __get__ receive as obj when the descriptor is accessed from the class rather than from an instance?

Vänligen välj det korrekta svaret

Var allt tydligt?

Hur kan vi förbättra det?

Tack för dina kommentarer!

Avsnitt 1. Kapitel 2

Fråga AI

expand

Fråga AI

ChatGPT

Fråga vad du vill eller prova någon av de föreslagna frågorna för att starta vårt samtal

Avsnitt 1. Kapitel 2
some-alt