Различия между версиями 8 и 9
Версия 8 от 2021-12-01 03:45:57
Размер: 5015
Редактор: alryaz
Комментарий:
Версия 9 от 2021-12-19 13:08:46
Размер: 5144
Редактор: FrBrGeorge
Комментарий:
Удаления помечены так. Добавления помечены так.
Строка 84: Строка 84:
   * сравнение быстродействия обоих классов на больших объёмах чтения/записи полей (должно получаться, что `Alpha` быстрее, чем `AlphaQ`)    * сравнение быстродействия обоих классов на достаточно больших объёмах чтения/записи полей (должно получаться, что `Alpha` быстрее, чем `AlphaQ`); точное время выводить не надо, только результат сравнения

11.18 Декораторы и дескрипторы

Декораторы

Декораторы — зачем нужны и синтаксис

  • {i} проверить, что все операнды функции — это int

  • Параметрические декораторы — это не страшно!
  • {i} проверить, что все операнды функции — это заданный тип

  • Декораторы классов
    • Часто не создают новый класс, а жуют и возвращают старый
    • Но можно и производный класс сделать
  • <!> Задача_1:

    • Написать декоратор_класса objcount, который добавляет в класс поле counter (это поле класса), в котором подсчитывается количество экземпляров этого класса.

    • (для начала) считает количество созданных экземпляров (перегрузка .__init__())

    • но в конце концов надо перегрузить и .__del__(), чтобы учитывать количество созданных, но не удалённых объектов

    • Стоит помнить, что .__del__() у класса может и не быть

    • Защищать поле .counter не надо

    • В тестах должна проверяться корректность работы на классах с собственным __init__() и __del__()

      Input:

      @objcount
      class C:
          pass
      
      c, d, e = C(), C(), C()
      print(C.counter)
      c = 100500
      print(C.counter)

      Output:

      3
      2

Дескрипторы

Дескрипторы — реализация шаблона getter/setter/deleter

  • Внутреннее устройство (это поле класса!)
    • non-data дескрипторы (getter only)
    • Где хранить то, что хранится в data дескрипторе?
  • {i} Обычный «шумный» дескриптор: хранит что угодно, но сообщает о действиях

  • @property — удобная обмазка вокруг дескрипторов

  • <!> Задача_2:

    • Написать дескриптор Num, который хранит только числа, а если пытаться присвоить ему последовательность, вычисляет и хранит её длину.

    • Числа имеют поле .real

    • Последовательности имеют метод .__len__()

      • если есть и то, и то, предпочтительнее real

    • Остальные случаи не проверять
    • По умолчанию значение поля типа Num = 0

      Input:

      class C:
        num = Num()
      print(C().num)
      c, d = C(), C()
      c.num = d.num = 2
      print(c.num+d.num)
      c.num = "qwerqwerqwer"
      print(c.num+d.num)
      d.num = range(10, 1000, 7)
      print(c.num+d.num)

      Output:

      0
      4
      14
      154

Слоты

Слоты — организация пространства имён экземпляра класса без __dict__

  • Прозрачно для пользователя (слоты RW, поля классов RO)
  • Эффективно, реализовано через дескрипторы
  • <!> Задача_3:

    • Написать с помощью слотов класс Alpha, полем которого является любая маленькая буква латинского алфавита, и никакая другая. Класс должен поддерживать методы .__init__(), именные параметры которого задают эти поля, и .__str__(), который выводит содержимое полей объекта в алфавитном порядке:

    • Написать аналогичный класс AlphaQ c помощью .__getattr__() и словаря

    • В тестах предусмотреть
      • проверку обоих классов на то, что несуществующие/незаданные поля инициируют AttributeError (так ведёт себя класс со слотами)

      • сравнение быстродействия обоих классов на достаточно больших объёмах чтения/записи полей (должно получаться, что Alpha быстрее, чем AlphaQ); точное время выводить не надо, только результат сравнения

      Input:

      alp = Alpha(c=10, z=2, a=42)
      alp.e = 123
      print(alp)
      alq = AlphaQ(c=10, z=2, a=42)
      alq.e = 123
      print(alq)

      Output:

      a: 42, c: 10, e: 123, z: 2
      a: 42, c: 10, e: 123, z: 2

LecturesCMC/PythonIntro2021/Prac/09_MiscOOP (последним исправлял пользователь FrBrGeorge 2021-12-19 13:08:46)