МУНИЦИПАЛЬНОЕ АВТОНОМНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ДОПОЛНИТЕЛЬНОГО ОБРАЗОВАНИЯ
«ЦЕНТР ДЕТСКОГО ТЕХНИЧЕСКОГО ТВОРЧЕСТВА»
Методическая разработка
«Протокол дескриптора в Python»
к дополнительной общеобразовательной
общеразвивающей программе
технической направленности
«Программирование на Python»
Возраст детей: 10-17 лет
Автор: Костычев Вадим Александрович
г. Заречный Пензенской области
2026 г.
Данный материал предназначен для преподавателей информатики, программирования и студентов (учащихся), изучающих язык программирования Python. Он может быть использован как на лекциях, так и при проведении практических занятий или самостоятельной работе.
Цель: сформировать у обучающихся понимание механизма дескрипторов как одного из фундаментальных протоколов Python, лежащего в основе работы property, classmethod, staticmethod и других механизмов языка, а также научить создавать собственные дескрипторы для управления доступом к атрибутам.
Задачи:
Объяснить, что такое дескриптор и зачем он нужен.
Познакомить с протоколом дескриптора: методами __get__, __set__, __delete__.
Различать data-дескрипторы и non-data-дескрипторы.
Показать, как дескрипторы используются в самом Python (property, classmethod, staticmethod).
Научить создавать собственные дескрипторы для валидации и управления атрибутами.
Продемонстрировать практическую пользу дескрипторов в реальных задачах.
Что такое дескриптор?
Дескриптор — это объект, который управляет доступом к атрибуту другого объекта через специальные магические методы.
Простыми словами:
Дескриптор — это «посредник», который перехватывает операции чтения, записи и удаления атрибута.
Дескрипторы лежат в основе многих встроенных механизмов Python:
property
@classmethod
@staticmethod
super()
методы классов в целом
Протокол дескриптора
Чтобы объект стал дескриптором, он должен реализовать хотя бы один из следующих методов:
class Descriptor:
def __get__(self, instance, owner=None):
# Вызывается при чтении атрибута
pass
def __set__(self, instance, value):
# Вызывается при записи атрибута
pass
def __delete__(self, instance):
# Вызывается при удалении атрибута
pass
Параметры методов:
| Параметр | Значение |
| self | Сам объект-дескриптор |
| instance | Экземпляр класса, у которого вызван атрибут |
| owner | Класс, которому принадлежит атрибут |
| value | Значение, которое присваивается |
Типы дескрипторов
Data-дескриптор (данные)
Реализует и __get__, и __set__ (или __delete__).
Имеет высокий приоритет — перекрывает атрибуты в __dict__ экземпляра.
Non-data-дескриптор (только чтение)
Реализует только __get__.
Имеет низкий приоритет — атрибут в __dict__ экземпляра перекроет дескриптор.
Порядок поиска атрибута:
Data-дескриптор из класса
Атрибут в __dict__ экземпляра
Non-data-дескриптор из класса
Атрибут в __dict__ класса
__getattr__, если определён
Простой пример дескриптора
Создадим дескриптор для логирования доступа к атрибуту:
class LoggedAttribute:
def __init__(self, name):
self.name = name
def __get__(self, instance, owner):
print(f"[GET] Чтение {self.name}")
return instance.__dict__.get(self.name)
def __set__(self, instance, value):
print(f"[SET] Запись {self.name} = {value}")
instance.__dict__[self.name] = value
def __delete__(self, instance):
print(f"[DEL] Удаление {self.name}")
del instance.__dict__[self.name]
class Person:
name = LoggedAttribute("_name")
age = LoggedAttribute("_age")
def __init__(self, name, age):
self.name = name # вызовет __set__
self.age = age # вызовет __set__
p = Person("Анна", 25)
# [SET] Запись _name = Анна
# [SET] Запись _age = 25
print(p.name) # [GET] Чтение _name → Анна
p.age = 30 # [SET] Запись _age = 30
del p.name # [DEL] Удаление _name
Практический пример: валидация атрибутов
Дескрипторы идеально подходят для проверки значений при присваивании:
class Validator:
def __init__(self, min_value=None, max_value=None):
self.min_value = min_value
self.max_value = max_value
def __set_name__(self, owner, name):
self.name = name
def __set__(self, instance, value):
if self.min_value is not None and value
raise ValueError(f"{self.name} должно быть = {self.min_value}")
if self.max_value is not None and value self.max_value:
raise ValueError(f"{self.name} должно быть
instance.__dict__[self.name] = value
def __get__(self, instance, owner):
if instance is None:
return self
return instance.__dict__.get(self.name)
class Product:
price = Validator(min_value=0)
quantity = Validator(min_value=0, max_value=1000)
def __init__(self, name, price, quantity):
self.name = name
self.price = price
self.quantity = quantity
p = Product("Книга", 500, 10)
p.price = 600 # OK
p.quantity = 500 # OK
# p.price = -100 # ValueError: price должно быть = 0
# p.quantity = 2000 # ValueError: quantity должно быть
Дескрипторы в самом Python
property — это дескриптор:
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@radius.setter
def radius(self, value):
if value
raise ValueError("Радиус не может быть отрицательным")
self._radius = value
Под капотом property — это data-дескриптор, реализующий __get__, __set__, __delete__.
@classmethod и @staticmethod — тоже дескрипторы!
Они реализуют __get__, чтобы возвращать связанные или несвязанные методы.
Data vs Non-data дескрипторы: пример
class NonDataDesc:
def __get__(self, instance, owner):
return "из дескриптора"
class DataDesc:
def __get__(self, instance, owner):
return "из data-дескриптора"
def __set__(self, instance, value):
pass
class MyClass:
non_data = NonDataDesc()
data = DataDesc()
obj = MyClass()
# Non-data дескриптор
print(obj.non_data) # "из дескриптора"
obj.__dict__["non_data"] = "из __dict__"
print(obj.non_data) # "из __dict__" __dict__ перекрывает!
# Data дескриптор
print(obj.data) # "из data-дескриптора"
obj.__dict__["data"] = "из __dict__"
print(obj.data) # "из data-дескриптора" дескриптор перекрывает!
Когда использовать дескрипторы?
| Ситуация | Пример |
| Валидация атрибутов | Проверка типов, диапазонов |
| Ленивые вычисления | Вычисление значения при первом обращении |
| Логирование | Отслеживание доступа к атрибутам |
| Кэширование | Сохранение результатов вычислений |
| Автоматизация | Повторяющаяся логика для нескольких атрибутов |
| Создание своих property-подобных механизмов | Кастомные геттеры/сеттеры |
Преимущества дескрипторов
Переиспользование — один дескриптор можно применить к множеству атрибутов
Чистый код — логика валидации вынесена из класса
Гибкость — полный контроль над чтением/записью/удалением
Производительность — быстрее, чем __getattr__/__setattr__
Основа языка — понимание дескрипторов = понимание Python
Заключение
Дескриптор — объект, управляющий доступом к атрибутам через __get__, __set__, __delete__.
Data-дескриптор (с __set__) имеет приоритет над __dict__ экземпляра.
Non-data-дескриптор (только __get__) уступает __dict__.
Дескрипторы лежат в основе property, classmethod, staticmethod.
Они идеальны для валидации, логирования, ленивых вычислений.
Понимание дескрипторов — ключ к глубокому пониманию Python.
Освоив протокол дескриптора, вы получаете доступ к одному из самых мощных механизмов Python — инструменту, на котором построены многие встроенные возможности языка. Это уровень продвинутого разработчика, понимающего, как работает Python изнутри.