Перечисление на основе строк в Python - PullRequest
2 голосов
/ 29 октября 2019

Чтобы инкапсулировать список состояний, я использую модуль enum:

from enum import Enum

class MyEnum(Enum):
    state1='state1'
    state2 = 'state2'

state = MyEnum.state1
MyEnum['state1'] == state  # here it works
'state1' == state  # here it does not throw but returns False (fail!)

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

select_query1 = select(...).where(Process.status == str(MyEnum.state1))  # works but ugly

select_query2 = select(...).where(Process.status == MyEnum.state1)  # throws exeption

Как это сделать, избегая вызова дополнительного преобразования типа (str(state) выше) или базового значения (state.value)?

Ответы [ 3 ]

4 голосов
/ 29 октября 2019

Кажется, что достаточно унаследовать от str класса одновременно с Enum:

class MyEnum(str, Enum):
    state1='state1'
    state2 = 'state2'

Сложность состоит в том, что порядок классов вцепочка наследования важна , как это:

class MyEnum(Enum, str):
    state1='state1'
    state2 = 'state2'

throws:

TypeError: new enumerations should be created as `EnumName([mixin_type, ...] [data_type,] enum_type)`

При правильном классе следующие операции на MyEnum в порядке:

print('This is the state value: ' + state)

В качестве примечания, похоже, что специальный прием наследования не требуется для форматированных строк , которые работают даже для Enum только наследования:

msg = f'This is the state value: {state}'  # works without inheriting from str
1 голос
/ 29 октября 2019

Хотя класс смешивания между str и Enum может решить эту проблему, вы всегда должны подумать о том, чтобы получить подходящий инструмент для работы .

И иногда правильным инструментом может быть просто MODULE_CONSTANT со строковым значением. Например, logging имеет несколько констант, таких как DEBUG, INFO и т. Д. Со значимыми значениями - даже если в этом случае они int s.

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

0 голосов
/ 29 октября 2019

Попробуйте изменить тип данных статуса в базе данных в соответствии с перечислением. Некоторые БД не разрешают или пытаются использовать временную копию таблицы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...