如何让Enum的成员进入全局命名空间?

时间:2015-01-24 21:54:19

标签: python enums

Python现在有一个枚举类型(3.4 with PEP 435中的新内容,另外还有backported),虽然命名空间是好事,但有时枚举更像常量,枚举成员应该活在全局(呃,模块)命名空间中。

所以而不是:

Constant(Enum):
    PI = 3.14

...

area = Constant.PI * r * r

我可以说:

area = PI * r * r

是否有从Constant.PIPI的简单方法?

2 个答案:

答案 0 :(得分: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本身设置一个较短的别名,并使用它而不是污染全局命名空间:

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

area = C.PI * r * r

答案 1 :(得分: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()方法{下一个Python版本中的{1}} base 类,因此它可以自动使用。