В этом уроке вы узнаете о перечислении в 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) 