Python перечисление из строки, выдает ошибку, если строка не в элементах - PullRequest
0 голосов
/ 24 февраля 2020

Мне интересно, могу ли я использовать перечисления python для принудительного ввода заданных c строковых входных данных от пользователя в мои функции и классы и во избежание необходимости кодировать явные проверки на допустимые значения.

Так вместо этого:

например,

utilities_supplied = {
    'electricity': 'Yes',
    'gas': 'No',
    'water': 'Yes',
}

def find_utility(utility):
    try:
        print(utilities_supplied[utility])
    except KeyError:
        raise KeyError(f'Please choose one of {utilities_supplied.keys()}, \'{utility}\' provided')

Я хотел бы сделать это:


from enum import Enum
class Utility(Enum):
    electricity = 1
    gas = 2
    water = 3

Utility['electric']  
# not a member, I want this to raise an error which lists the acceptable options.

Возможно ли для перечислений выдавать ошибку, перечисляя возможные члены перечисления?

Ответы [ 2 ]

1 голос
/ 24 февраля 2020

Вы можете использовать EnumMeta для перезаписи __getitem__, которая выбирает значения из перечисления:

import enum


class MyEnum(enum.EnumMeta):
    def __getitem__(cls, name):
        try:
            return super().__getitem__(name)
        except (KeyError) as error:
            options = ', '.join(cls._member_map_.keys())
            msg = f'Please choose one of {options}, \'{name}\' provided'
            raise ValueError(msg) from None


class Utility(enum.Enum, metaclass=MyEnum):
    electricity = 1
    gas = 2
    water = 3


fire = Utility['fire']
print(fire)

Вывод:

ValueError: Please choose one of electricity, gas, water, 'fire' provided
0 голосов
/ 28 февраля 2020

РЕДАКТИРОВАТЬ: Это действительно не работает, когда я подкласс класса ValidatedEnum. Любая помощь с благодарностью получена.

Решение с использованием _missing_ оказалось довольно простым, оказывается! Спасибо за идею @ EthanFurman.

from enum import Enum
class ValidatedEnum(Enum):
    electricity = 1
    gas = 2
    water = 3

    @classmethod
    def _missing_(cls, value):
        choices = list(cls.__members__.keys())
        raise ValueError("%r is not a valid %s, please choose from %s" % (value, cls.__name__, choices))

<ipython-input-1-8b49d805ac2d> in _missing_(cls, value)
      8     def _missing_(cls, value):
      9         choices = list(cls.__members__.keys())
---> 10         raise ValueError("%r is not a valid %s, please choose from %s" % (value, cls.__name__, choices))
     11 

ValueError: 'electric' is not a valid ValidatedEnum, please choose from ['electricity', 'gas', 'water']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...