是否可以在 Python 3 中直接导入枚举字段?

is it possible to directly import an enum field in Python 3?

假设我有以下枚举:

class LineStyle(Enum):
    SOLID = 'solid'
    DASHED = 'dashed'
    DASHDOT = 'dashdot'
    DOTTED = 'dotted'

是否可以通过某种方式直接从该枚举中导入字段?

例如:

from mymodule.LineStyle import SOLID, DASHED  # does not work

我能想到的唯一解决方法是将所有枚举字段声明为模块变量:

class LineStyle(Enum):
    SOLID = 'solid'
    DASHED = 'dashed'
    DASHDOT = 'dashdot'
    DOTTED = 'dotted'

SOLID = LineStyle.SOLID
DASHED = LineStyle.DASHED
DASHDOT = LineStyle.DASHDOT
DOTTED = LineStyle.DOTTED

有没有更优雅的方法来做到这一点?

没有。使用 import 只能在当前命名空间中添加指向模块对象本身或模块中顶级名称的引用。枚举值不是模块中的顶级名称,除非您明确地将它们放在那里,就像在您的解决方法中一样。

可以 自动将这些名称分配给全局变量,方法是将 __members__ attribute 中的所有信息添加到您的模块全局变量中:

globals().update(LineStyle.__members__)

globals() function gives you a reference to the namespace of the current module, letting you add names to that namespace dynamically. The LineStyle.__members__ attribute is a a mapping of name to value (including aliases), 所以上面把所有名字都加到全局命名空间中:

>>> from enum import Enum
>>> class LineStyle(Enum):
...     SOLID = 'solid'
...     DASHED = 'dashed'
...     DASHDOT = 'dashdot'
...     DOTTED = 'dotted'
...
>>> SOLID
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'SOLID' is not defined
>>> globals().update(LineStyle.__members__)
>>> SOLID
<LineStyle.SOLID: 'solid'>

如果您不想在其中包含别名,请使用 for 循环,遍历 LineStyle 对象。这只会为您提供成员对象,然后您可以从中提取名称:

for member in LineStyle:
    globals()[member.name] = member

您不能直接导入 enum 成员,但您可以使用装饰器将 Enum 成员自动添加到 globals(),这样就可以导入了。例如:

def global(enum):
    globals().update(enum.__members__)
    return enum


@global
class LineStyle(Enum):
    SOLID = 'solid'
    DASHED = 'dashed'
    DASHDOT = 'dashdot'
    DOTTED = 'dotted'