使 Python 枚举安全用于交互式工作,其中可以多次执行文件

问题描述

如果我在 Python 中进行交互式工作并且有一个看起来像这样的 Enum

from enum import Enum
class UnsafeColor(Enum):
     RED = 1
     GREEN = 2
     BLUE = 3

我可以做

[In]: socks = UnsafeColor.RED
<rerun file>
[In]: shoes = UnsafeColor.RED
[In]: socks == shoes
[Out]: False

这有点令人惊讶,但问题是重新运行文件会创建一个新的 UnsafeColor 类,其成员与旧的不同。我可以通过做类似的事情来避免这种情况

from functools import lru_cache
try:
    get_interactive_safe_enum
except NameError as e:
    @lru_cache(maxsize=None)
    def get_interactive_safe_enum(*args,**kwargs):
        return Enum(*args,**kwargs)

SafeColor = get_interactive_safe_enum("SafeColor","RED GREEN BLUE")

现在以下按预期工作:

[In]: hat = SafeColor.RED
<rerun file>
[In]: shirt = SafeColor.RED
[In]: hat == shirt
[Out]: True

这行得通,但没有赢得任何奖项。 Enum 似乎有很多单例和元类魔法,所以我想知道有没有更好的方法来实现这一点?

解决方法

您遇到的问题是 <rerun file> 步骤。在 Python 2 中,它是一个内置拼写 reload(),而在 Python 3 中,它隐藏在一个模块中,因为它是一个有吸引力的麻烦——正是你上面陈述的原因。

Python 的任何模块都没有被设计为“重新运行”,您会发现在重新运行之前保存的每个带有单例的模块(例如上面的袜子)都将在新的重新运行文件(您的上面的鞋子)。

换句话说,这不是 Enum 问题 -- 这是 Python 的设计方式。如果您重新运行一个模块,请注意更新您之前保存的任何内容——模块变量、函数、类和单例。


添加一些希望有用的建议——将常量和不需要重新加载的内容保存在自己的文件中;当 <rerun file> get 重新运行时,它仍将导入已经运行且不再运行的常量文件,并且您的枚举和其他常量将相同。