Как получить членов Enum в глобальном пространстве имен?

python enums

483 просмотра

2 ответа

Python теперь имеет тип Enum (новый в 3.4 с PEP 435 и alse backported ), и хотя пространства имен - это хорошая вещь, иногда Enums используются скорее как константы, и члены enum должны жить в глобальном (er, module) пространстве имен ,

Так что вместо:

Constant(Enum):
    PI = 3.14

...

area = Constant.PI * r * r

Я могу просто сказать:

area = PI * r * r

Есть ли простой способ перейти от Constant.PIпросто PI?

Автор: Ethan Furman Источник Размещён: 12.11.2019 09:40

Ответы (2)


4 плюса

Решение

Официально поддерживаемый метод выглядит примерно так:

globals().update(Constant.__members__)

Это работает, потому что __members__это dict-подобный объект, который содержит имена и члены класса Enum.

Лично я нахожу это настолько уродливым, что обычно добавляю следующий метод в мои классы Enum:

@classmethod
def export_to(cls, namespace):
    namespace.update(cls.__members__)

и тогда в моем коде верхнего уровня я могу сказать:

Constant.export_to(globals())

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

class Constant(Enum):
    PI = ....
C = Constant

area = C.PI * r * r
Автор: Ethan Furman Размещён: 24.01.2015 09:54

0 плюса

FWIW - это скорее комментарий, а не ответ - ниже приведено начало функции из какого-то старого кода, который я написал, который реализует свои именованные intобъекты, подобные перечисляемым значениям, которые были добавлены в глобальное пространство имен по умолчанию (нет именованных контейнер Enum classвовлечен). Однако он делает нечто похожее на то, что показано в вашем собственном ответе, поэтому я считаю, что это хороший общий подход, потому что он хорошо сработал для меня.

def Enum(names, values=None, namespace=None):
    """Function to assign values to names given and add them to a
    namespace. Default values are a sequence of integers starting at
    zero. Default namespace is the caller's globals."""
    if namespace is None:
        namespace = sys._getframe(1).f_globals  # caller's globals

    pairs = _paired(names, values)
    namespace.update(pairs)  # bind names to cooresponding named numbers
        . . .

Дело в том, что для реализации чего-либо для текущего Enumмодуля класса я бы предложил добавить что-то вроде этого или def export_to()метод, показанный в вашем собственном ответе, к Enum базовому классу в следующем выпуске Python, чтобы он был доступен автоматически.

Автор: martineau Размещён: 24.01.2015 11:36
Вопросы из категории :
32x32