СДЕЛАЙТЕ СВОИ УРОКИ ЕЩЁ ЭФФЕКТИВНЕЕ, А ЖИЗНЬ СВОБОДНЕЕ

Благодаря готовым учебным материалам для работы в классе и дистанционно

Скидки до 50 % на комплекты
только до

Готовые ключевые этапы урока всегда будут у вас под рукой

Организационный момент

Проверка знаний

Объяснение материала

Закрепление изученного

Итоги урока

Методическая разработка «Типы дескрипторов в Python»

Категория: Информатика

Нажмите, чтобы узнать подробности

Просмотр содержимого документа
«Методическая разработка «Типы дескрипторов в Python»»

МУНИЦИПАЛЬНОЕ АВТОНОМНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ДОПОЛНИТЕЛЬНОГО ОБРАЗОВАНИЯ

«ЦЕНТР ДЕТСКОГО ТЕХНИЧЕСКОГО ТВОРЧЕСТВА»













Методическая разработка

«Типы дескрипторов в Python»

к дополнительной общеобразовательной

общеразвивающей программе

технической направленности

«Программирование на Python»



Возраст детей: 10-17 лет









Автор: Костычев Вадим Александрович











г. Заречный Пензенской области

2026 г.

Данный материал предназначен для преподавателей информатики, программирования и студентов (учащихся), изучающих язык программирования Python. Он может быть использован как на лекциях, так и при проведении практических занятий или самостоятельной работе.

Цель: сформировать у обучающихся понимание дескриптора данных как механизма контроля над присваиванием и удалением атрибутов, а также научить правильно хранить значения атрибутов внутри экземпляра класса-владельца, избегая типичных ошибок проектирования.

Задачи:

  1. Дать строгое определение дескриптора данных.

  2. Разобрать сигнатуру и параметры метода __set__.

  3. Показать, как работает __set__ при присваивании значения атрибуту.

  4. Проанализировать три способа хранения значений в дескрипторе и их недостатки.

  5. Научить правильно организовывать хранение данных через __init__ и уникальные имена атрибутов.

  6. Подготовить почву для изучения метода __set_name__ как более элегантного решения.

Что такое дескриптор данных?

Дескриптор данных (data descriptor) — это объект, целью которого является контроль установки и удаления атрибутов других объектов.

Строгое определение:

Объект, в котором реализован хотя бы один из методов __set__ или __delete__, называется data-дескриптором.

Как правило, в data-дескрипторе также реализуется метод __get__, чтобы обеспечить полный цикл работы с атрибутом: чтение, запись и удаление.

💡 Ключевое отличие от non-data-дескриптора: наличие __set__ или __delete__. Именно эти методы делают дескриптор «данным» — он управляет реальным состоянием.


Метод __set__: сигнатура и параметры

Метод __set__ вызывается автоматически при присваивании значения атрибуту.

Сигнатура:

def __set__(self, instance, value) - None:

...


Параметры:


Параметр

Что представляет

self

Сам экземпляр дескриптора

instance

Экземпляр класса-владельца, через который идёт присваивание

value

Значение, которое присваивается

Пример, демонстрирующий вызов:

class CoordinateValue:

def __set__(self, instance, value):

print(f'__set__ вызван: instance={instance}, value={value}')


def __get__(self, instance, owner_class):

if instance is None:

print('__get__ вызван от класса')

else:

print(f'__get__ вызван: instance={instance}, owner={owner_class}')



class Point:

x = CoordinateValue()

y = CoordinateValue()



Point.x # __get__ вызван от класса


p = Point()

p.x # __get__ вызван: instance=, owner=

p.x = 100 # __set__ вызван: instance=, value=100


Метод __set__ срабатывает только при присваивании (p.x = 100), а не при чтении.


Главный вопрос: где хранить значение?

После вызова __set__ возникает ключевой вопрос: куда сохранить переданное значение?

Существует три основных подхода, расположенных от худшего к лучшему:

  1. Сохранение внутри экземпляра дескриптора

  2. Сохранение внутри экземпляра класса-владельца (с фиксированным именем)

  3. Сохранение внутри экземпляра класса-владельца (с уникальным именем через __init__)

Разберём каждый из них.


Способ 1: Хранение внутри экземпляра дескриптора (ПЛОХО)

Идея: сохранить значение в атрибуте самого дескриптора, например _value.

class CoordinateValue:

def __set__(self, instance, value):

self._value = int(value)


def __get__(self, instance, owner_class):

if instance is None:

return self

return self._value



class Point:

x = CoordinateValue()

y = CoordinateValue()



p1 = Point()

p1.x = 100

p1.y = 200

print(p1.x, p1.y) # 100 200 ✓


p2 = Point()

print(p2.x, p2.y) # 100 200 УЖАС!

p2.x = 5

print(p1.x, p2.x) # 5 5 изменение p2 повлияло на p1!


Проблема: экземпляры дескриптора CoordinateValue() общие для всех объектов Point. Поэтому все точки делят одно и то же значение _value. Вывод: такой способ не работает — экземпляры влияют друг на друга.


Способ 2: Хранение в экземпляре класса-владельца с фиксированным именем (ПЛОХО)

Идея: сохранять значение в instance через атрибут с фиксированным именем, например _stored_value.

class CoordinateValue:

def __set__(self, instance, value):

instance._stored_value = int(value)


def __get__(self, instance, owner_class):

if instance is None:

return self

return getattr(instance, '_stored_value', None)



class Point:

x = CoordinateValue()

y = CoordinateValue()



p1 = Point()

p1.x = 77

print(p1.x, p1.y) # 77 77 оба атрибута показывают одно значение!

print(p1.__dict__) # {'_stored_value': 77}


p1.y = 5

print(p1.x, p1.y) # 5 5 y перезаписал x!


Проблема: оба дескриптора (x и y) сохраняют значение в один и тот же атрибут _stored_value. Каждое новое присваивание затирает предыдущее. Вывод: нужно уникальное имя для каждого атрибута-дескриптора.

Способ 3: Хранение с уникальным именем через __init__ (ХОРОШО)

Идея: при создании дескриптора передавать ему имя атрибута, под которым он будет хранить значение в экземпляре.

class CoordinateValue:

def __init__(self, name):

self.storage_name = '_' + name # уникальное имя для каждого дескриптора


def __set__(self, instance, value):

setattr(instance, self.storage_name, int(value))


def __get__(self, instance, owner_class):

if instance is None:

return self

return getattr(instance, self.storage_name, None)



class Point:

x = CoordinateValue('x')

y = CoordinateValue('y')



p1 = Point()

p1.x = 77

p1.y = 33

print(p1.x, p1.y) # 77 33 ✓

print(p1.__dict__) # {'_x': 77, '_y': 33}


p2 = Point()

p2.x = 2

p2.y = 3

print(p2.x, p2.y) # 2 3 ✓

print(p2.__dict__) # {'_x': 2, '_y': 3}


Преимущества:

  • Каждый экземпляр имеет свои собственные значения

  • Разные атрибуты-дескрипторы не затирают друг друга

  • Значения хранятся в __dict__ экземпляра класса-владельца

Недостаток: необходимость вручную передавать имя при инициализации:

x = CoordinateValue('x') # дублирование имени!

Это неудобно и подвержено ошибкам. В следующем уроке мы рассмотрим метод __set_name__, который автоматически передаёт имя атрибута в дескриптор.


Сравнительная таблица способов хранения


Способ

Где хранится

Проблема

Внутри дескриптора

self._value

Все экземпляры делят одно значение

В экземпляре, фиксированное имя

instance._stored_value

Разные атрибуты затирают друг друга

В экземпляре, уникальное имя

instance._x, instance._y

Нужно вручную передавать имя

В экземпляре + __set_name__

instance._x (автоматически)

Идеальный способ




Практические рекомендации

  1. Никогда не храните состояние в самом дескрипторе — это приведёт к общим значениям для всех экземпляров.

  2. Всегда храните данные в экземпляре класса-владельца — это гарантирует независимость объектов.

  3. Используйте уникальные имена для каждого атрибута-дескриптора.

  4. Избегайте ручного указания имён — переходите к __set_name__ как можно скорее.

  5. Используйте setattr/getattr для работы с динамическими именами атрибутов.


Заключение

  1. Data-дескриптор — объект с методами __set__ и/или __delete__.

  2. Метод __set__(self, instance, value) вызывается при присваивании атрибуту.

  3. Хранить значения внутри дескриптора нельзя — экземпляры будут влиять друг на друга.

  4. Хранить значения в экземпляре класса-владельца — правильный подход.

  5. Для разных атрибутов нужны уникальные имена в __dict__.

  6. Передача имени через __init__ решает проблему, но неудобна.

  7. Следующий шаг — использование __set_name__ для автоматического получения имени.

Освоив дескриптор данных, вы получаете точный инструмент управления атрибутами с полным контролем над их установкой. Понимание того, где и как хранить значения, — ключ к созданию надёжных и предсказуемых дескрипторов.