#python #python-3.x #enums
#python #python-3.x #перечисления
Вопрос:
Я использую классы Enum для явного отображения возможных значений аргумента. Это красиво и лаконично.
Однако, когда я обращаюсь к одному перечислению из другого, оно начинает выглядеть непитоническим : Functions[day.value].value
. Тот факт, что мне нужно передать и получить атрибут value Enum, добавляет сложности.
Как можно переписать этот (вымышленный) код, чтобы использовать только одно перечисление и не нуждаться в доступе к value
атрибуту?
from datetime import datetime, timedelta
from enum import Enum
class Day(Enum):
YESTERDAY = 'YESTERDAY'
TODAY = 'TODAY'
TOMORROW = 'TOMORROW'
def get_date(day: Day):
class Functions(Enum):
YESTERDAY = datetime.now() timedelta(days=-1)
TODAY = datetime.now()
TOMORROW = datetime.now() timedelta(days=1)
return Functions[day.value].value.date()
today = get_date(Day.TODAY)
yesterday = get_date(Day.YESTERDAY)
tomorrow = get_date(Day.TOMORROW)
Комментарии:
1. Я бы не стал использовать enum для подобных динамических данных, обычный класс кажется более подходящим…
2. Вы делаете это, чтобы избежать if / else ? В python вы также можете использовать для этого dict
return {Day.TODAY: datetime.now(), ...}.get(day)
, который для меня выглядит более питоническим. Я также немного обеспокоен тем, что время / место объявленияFunctions
enum влияет на его значения… но это может быть только я
Ответ №1:
Мне кажется, что вы пытаетесь реализовать switch
оператор, которого нет в python. Наиболее распространенный способ, который я видел, используемый для выполнения такой задачи, — это dict
:
def get_date(day: Day):
return {
Day.YESTERDAY: datetime.now() timedelta(days=-1),
Day.TODAY: datetime.now(),
Day.TOMORROW: datetime.now() timedelta(days=1),
}[day].date()
Обратите внимание, что я обращаюсь [day]
напрямую, что может вызвать KeyError. Если вы хотите избежать этого, вы можете использовать get(day, default=datetime.now())
which по существу пытается получить доступ к ключу, и если он не существует, он возвращается datetime.now()
.
Ответ №2:
Для Enum возможно иметь другие атрибуты, кроме name
и value
— например, date
:
from datetime import date, timedelta
from enum import Enum
class Day(Enum):
YESTERDAY = 'YESTERDAY'
TODAY = 'TODAY'
TOMORROW = 'TOMORROW'
#
@property
def date(self):
today = date.today()
return {
'YESTERDAY': today timedelta(days=-1),
'TODAY': today,
'TOMORROW': today timedelta(days=1),
}[self.value]
и используется:
>>> Day.YESTERDAY
<Day.YESTERDAY: 'YESTERDAY'>
>>> Day.YESTERDAY.date
datetime.date(2020, 11, 9)
>>> Day.TODAY
<Day.TODAY: 'TODAY'>
>>> Day.TODAY.date
datetime.date(2020, 11, 10)
>>> Day.TOMORROW
<Day.TOMORROW: 'TOMORROW'>
>>> Day.TOMORROW.date
datetime.date(2020, 11, 11)
Раскрытие информации: я являюсь автором Python stdlib Enum
, enum34
backport и расширенной библиотеки Enumeration ( aenum
).