问题描述
如果我在 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 重新运行时,它仍将导入已经运行且不再运行的常量文件,并且您的枚举和其他常量将相同。