Классы IntEnum и StrEnum

Курс по стандартной библиотеке: https://stepik.org/a/259466?utm_source=proproprogs

Смотреть материал на YouTube | RuTube

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

  • IntEnum – для создания перечисления из набора целых чисел;
  • StrEnum – для создания перечисления из набора строк.

Давайте посмотрим, чем эти классы отличаются от ранее рассмотренного класса Enum. Предположим, что нам нужно сформировать перечисление для дней недели. Сделаем это следующим образом:

import enum
 
 
class Week(enum.IntEnum):
    Monday = 1
    Tuesday = 2
    Wednesday = 3
    Thursday = 4
    Friday = 5
    Saturday = 6
    Sunday = 7

С элементами такого перечисления возможны следующие операции:

p1 = Week.Monday
p2 = Week.Friday
 
p1 == Week.Monday # True
p1 == 1 # True
p1 == Week.Thursday # False
p1 == p2 # False
p1.value # 1
p2.name # 'Friday'
p1 + p2 # 6
p1 < p2 # True
p2 <= p1 # False

Обратите внимание, объекты p1, p2 можно сравнивать на равенство не только с объектами Week.Monday, Week.Thursday, но и с конкретными числами. Кроме того, с p1, p2 можно выполнять различные арифметические операции, как с целыми числами, что было недопустимо с объектами обычного перечисления Enum. Кроме того, если попытаться присвоить какому-либо атрибуту значение, не приводящееся к целочисленному, например:

class Week(enum.IntEnum):
    Monday = 'a'
    ...

то при выполнении программы возникнет ошибка ValueError. То есть, класс IntEnum гарантирует целочисленные значения своих элементов и расширяет их операции до сравнения с числами и различных арифметических действий.

Пример использования перечисления IntEnum

Рассмотрим небольшой пример использования данного перечисления. Объявим функцию, которая будет выдавать список предметов для указанного дня:

def get_subjects(day: Week):
    match day:
        case Week.Monday:
            return "Информатика", "Математика"
        case Week.Tuesday:
            return "Физика",
        case Week.Friday:
            return "Машинное обучение", "Математика", "Информатика"
        case _:
            return tuple()

Здесь используется конструкция match/case для выбора указанного дня и если шаблон проверки совпадает, то возвращается кортеж из названий дисциплин. Последний case реализует поведение по умолчанию, возвращающий пустой кортеж.

Воспользоваться этой функцией можно следующим образом:

subjects = get_subjects(Week.Friday)
print(subjects)

После запуска программы, получим:

('Машинное обучение', 'Математика', 'Информатика')

Обратите внимание, что из-за использования типа IntEnum, мы можем в аргументе указать целое число, соответствующее дню Friday:

subjects = get_subjects(5)

Результат будет тем же.

Перечисления типа StrEnum

По аналогии работает перечисление типа StrEnum, которое в качестве значений атрибутов требует строковые данные. Например:

class Filter(enum.StrEnum):
    ASC = 'ascend'
    DESC = 'descent'
    BYID = 'id'

Который можно также перебрать с помощью цикла for:

for p in Filter:
    print(f"{p.name}: {p.value}")

Или, извлечь любое значение по имени атрибута:

p1 = Filter.DESC # <enum 'Filter'>
p2 = Filter['ASC'] # <enum 'Filter'>

Каждый элемент будет являться объектом класса Filter. С этими элементами допустимы следующие операции:

p1 == p2 # False
p2 == Filter.ASC # True
p1 < Filter.BYID # True (лексикографическое сравнение строк)
p2 >= Filter.DESC # False
p1 + p2 # 'descentascend'

То есть, можно выполнять те же операции, что и со строками.

Если при объявлении перечисления типа StrEnum в значении какого-либо атрибута указать не строковую величину, например:

class Filter(enum.StrEnum):
    ASC = 'ascend'
    DESC = 'descent'
    BYID = 'id'
 
    p1 = ('1', '2') # ошибка (кортеж)
    p2 = 5 # ошибка (число)

то возникнет ошибка TypeError. Здесь следует явно прописывать строки или строковые переменные.

Вот так классы перечислений Enum, IntEnum, StrEnum позволяют структурировать данные, делая код понятнее и надежнее. Их использование повышает качество программного продукта благодаря строгому контролю над допустимым набором значений. Поэтому, если в проекте требуется ограничение списка возможных состояний, то для этого очень хорошо подходят классы перечислений.

Курс по стандартной библиотеке: https://stepik.org/a/259466?utm_source=proproprogs

Видео по теме