Enum — перечисления в Python

В этом уроке вы узнаете о перечислении в Python и о том, как его эффективно использовать.

Содержание

Что такое перечисление в Python?

По определению перечисление — это набор членов, которым связаны уникальные константные значения. Перечисления в Python часто называют enum.

Python предоставляет вам модуль enum, содержащий тип Enum для определения новых перечислений. И вы определяете новый тип перечисления, создавая подкласс класса Enum.

В следующем примере показано, как создать перечисление под названием Color:

from enum import Enum


class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

Как это работает.

  • Сначала импортируйте тип Enum из модуля enum:
from enum import Enum
  • Во-вторых, определите класс Color, который наследуется от типа Enum:
class Color(Enum):
  • В-третьих, определите члены перечисления Color:
RED = 1
GREEN = 2
BLUE = 3

Обратите внимание, что члены перечисления являются константами. Поэтому их имена по традиции пишутся заглавными буквами.

В этом примере Color является перечислением. RED, GREEN и BLUE являются членами перечисления Color. Они имеют связанные значения 1, 2 и 3.

Ниже показано, что тип Color.RED — это перечисление Color:

print(type(Color.RED))

Выход:

<enum 'Color'>

Color.RED также является экземпляром перечисления Color:

print(isinstance(Color.RED, Color))

Выход:

True

И у него есть атрибуты name и value:

print(Color.RED.name)
print(Color.RED.value)

Выход:

RED
1

Членство и равенство

Чтобы проверить, включен ли элемент в перечисление, вы используете оператор in. Например:

if Color.RED in Color:
    print('Yes')

Выход:

Yes

Чтобы сравнить два элемента перечисления, вы можете использовать оператор is или ==. Например:

if Color.RED is Color.BLUE:
    print('red is blue')
else:
    print('red is not blue')

Выход:

red is not blue

Обратите внимание, что член перечисления и связанное с ним значение не равны. Следующий пример возвращает False:

if Color.RED == 1:
    print('Color.RED == 1')
else:
    print('Color.RED != 1')

Выход:

Color.RED != 1

Хеширование элементов перечисления

Члены перечисления всегда хешируются. Это означает, что вы можете использовать их как ключи в словаре или как элементы набора.

В следующем примере используются члены перечисления Color в словаре:

rgb = {
    Color.RED: '#ff0000',
    Color.GREEN: '#00ff00',
    Color.BLUE: '#0000ff'
}

Доступ к элементам по имени и значению

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

Color.RED

Поскольку Enum реализует метод __getitem__, вы также можете использовать синтаксис квадратных скобок [] для получения элемента по его имени.

Например, в следующем примере используется синтаксис квадратных скобок [] для получения члена RED перечисления Color по его имени:

print(Color['RED'])

Выход:

Color.RED

Поскольку перечисление является вызываемым, вы можете получить элемент по его значению. Например, следующая команда возвращает элемент RED перечисления Color по его значению:

print(Color(1))

Выход:

Color.RED

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

print(Color['RED'] == Color(1))

Выход:

True

Как перебирать члены перечисления

Перечисления являются итерируемыми, поэтому вы можете перебирать их с помощью цикла for. Например:

for color in Color:
    print(color)

Выход:

Color.RED
Color.GREEN
Color.BLUE

Обратите внимание, что порядок элементов такой же, как и в определении перечисления.

Кроме того, вы можете использовать функцию list() для возврата списка членов перечисления:

print(list(Color))

Выход:

[<Color.RED: 1>, <Color.GREEN: 2>, <Color.BLUE: 3>]

Перечисление неизменяемо

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

В следующем примере предпринимается попытка назначить новый элемент перечислению Color, что приводит к возникновению ошибки TypeError:

Color['YELLOW'] = 4

Ошибка:

TypeError: 'EnumMeta' object does not support item assignment

В следующем примере предпринимается попытка изменить значение члена RED перечисления Color и возникает ошибка AttributeError:

Color.RED.value = 100

Выход:

AttributeError: can't set attribute

Наследование перечисления

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

class Color(Enum):
    pass


class RGB(Color):
    RED = 1
    GREEN = 2
    BLUE = 3

Однако следующий пример не будет работать, поскольку перечисление RGB имеет члены:

class RGBA(RGB):
    ALPHA = 4

Ошибка:

TypeError: Cannot extend enumerations

Пример с перечислением в Python

В следующем примере определяется перечисление ResponseStatus:

class ResponseStatus(Enum):
    PENDING = 'pending'
    FULFILLED = 'fulfilled'
    REJECTED = 'rejected'

Предположим, вы получили ответ на HTTP-запрос со следующей строкой:

response = '''{
    "status":"fulfilled"
}'''

И вы хотите найти перечисление ResponseStatus по статусу. Для этого вам нужно преобразовать строку ответа в словарь и получить значение статуса:

import json

data = json.loads(response)
status = data['status']

Затем вы ищете член перечисления ResponseStatus по значению статуса:

print(ResponseStatus(status))

Выход:

PromiseStatus.FULFILLED

Вот полная программа:

from enum import Enum
import json


class ResponseStatus(Enum):
    PENDING = 'pending'
    FULFILLED = 'fulfilled'
    REJECTED = 'rejected'


response = '''{
    "status":"fulfilled"
}'''

data = json.loads(response)
status = data['status']

print(ResponseStatus(status))

Что, если статус не является одним из значений членов ResponseStatus? тогда вы получите ошибку. Например:

from enum import Enum
import json


class ResponseStatus(Enum):
    PENDING = 'pending'
    FULFILLED = 'fulfilled'
    REJECTED = 'rejected'


response = '''{
    "status":"ok"
}'''

data = json.loads(response)
status = data['status']

print(ResponseStatus(status))

Ошибка:

ValueError: 'ok' is not a valid ResponseStatus

Чтобы перехватить исключение, вы можете использовать оператор try…except:

from enum import Enum
import json


class ResponseStatus(Enum):
    PENDING = 'pending'
    FULFILLED = 'fulfilled'
    REJECTED = 'rejected'


response = '''{
    "status":"ok"
}'''

data = json.loads(response)
status = data['status']

try:
    if ResponseStatus(status) is ResponseStatus.FULFILLED:
        print('The request completed successfully')
except ValueError as error:
    print(error)
Похожие посты
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *