Python中的枚举不能按预期工作

aar*_*gon 6 python enums enumeration python-3.x

我在Python的Enum类中发现了一个非常奇怪的行为.所以枚举类型很简单:

from enum import Enum
Analysis = Enum('Analysis', 'static dynamic')
Run Code Online (Sandbox Code Playgroud)

所以我将这个枚举类型用于步骤对象,以便它们将它存储在属性分析中,如下所示:

class Step:
    def __init__(self):
        self.analysis = None
        self.bcs = []
Run Code Online (Sandbox Code Playgroud)

到目前为止非常简单,所以当我在列表中有一些这些步骤时,我会尝试查看枚举类型并且已正确分配.但他们并不平等:

# loop over steps
for s, step in enumerate(kwargs['steps']):
    print(kwargs)
    print(step)
    print(step.analysis)
    print("test for equality: ",(step.analysis == Analysis.static))
    quit()
Run Code Online (Sandbox Code Playgroud)

打印

{'mesh': <fem.mesh.mesh.Mesh object at 0x10614d438>,
 'steps': [<hybrida.fem.step.Step object at 0x10614d278>,
           <hybrida.fem.step.Step object at 0x10616a710>,
           <hybrida.fem.step.Step object at 0x10616a390>]}
Step:
  analysis: Analysis.static
  bcs: [<hybrida.fem.conditions.dirichlet.Dirichlet object at 0x10616a0f0>,
        <hybrida.fem.conditions.dirichlet.Dirichlet object at 0x10616a320>,
        <hybrida.fem.conditions.dirichlet.Dirichlet object at 0x10616a3c8>,
        <hybrida.fem.conditions.dirichlet.Dirichlet object at 0x10616a470>,
        <hybrida.fem.conditions.dirichlet.Dirichlet object at 0x10616a518>,
        <hybrida.fem.conditions.dirichlet.Dirichlet object at 0x10616a5c0>,
        <hybrida.fem.conditions.dirichlet.Dirichlet object at 0x10616a668>]
Analysis.static
test for equality:  False
Run Code Online (Sandbox Code Playgroud)

这是不正确的,但我对如何调试它没有任何想法.

UPDATE

根据@martineau的建议,我创建了一个IntEnum而不是解决了我的问题.然而,我不明白为什么正常Enum不起作用.

jme*_*jme 13

在评论中,你说:

输入文件包含许多步骤,每次添加新步骤时,我都必须设置分析类型

如果我理解正确,那么Enum每次添加新步骤时都会创建一个新对象.这可能就是你看到你的"虫子"的原因.Enum尽管具有相同的名称和顺序,但两个不同对象的值不一定相等.例如:

import enum
Analysis1 = enum.Enum("Analysis", "static dynamic")
Analysis2 = enum.Enum("Analysis", "static dynamic")
Run Code Online (Sandbox Code Playgroud)

但:

>>> Analysis1.static == Analysis2.static
False
Run Code Online (Sandbox Code Playgroud)

发生这种情况是因为Enum我没有为对象定义相等运算符,因此使用了检查ids 的默认行为.

正如@martineau在评论中建议的那样,避免这个问题的一种方法是改为使用IntEnum类型,即子类int,因此根据的值定义相等运算符Enum,而不是id:

import enum
Analysis1 = enum.IntEnum("Analysis", "static dynamic")
Analysis2 = enum.IntEnum("Analysis", "static dynamic")
Run Code Online (Sandbox Code Playgroud)

然后:

>>> Analysis1.static == Analysis2.static
True
Run Code Online (Sandbox Code Playgroud)

为什么Enum IntEnum

它可能乍一看似乎IntEnum总是我们想要的.那有什么意义Enum呢?

假设您要枚举两组项目,例如水果和颜色.现在,"橙色"既是水果又是颜色.所以我们写道:

Fruits = enum.IntEnum("Fruits", "orange apple lemon")
Colors = enum.IntEnum("Colors", "orange red blue")
Run Code Online (Sandbox Code Playgroud)

但现在:

>>> Fruits.orange == Colors.orange
True
Run Code Online (Sandbox Code Playgroud)

但是,从哲学上讲,"橙色"(水果)与"橙色"(颜色)不一样!我们不应该能够区分这两者吗?在这里,的子类int通过IntEnum对我们的作品,因为这两个Fruits.orangeColors.orange等同于1.当然,正如我们上面所看到的,Enums的比较比较ids而不是值.由于Fruits.orange并且Colors.orange是唯一的对象,因此它们不相等:

Fruits = enum.Enum("Fruits", "orange apple lemon")
Colors = enum.Enum("Colors", "orange red blue")
Run Code Online (Sandbox Code Playgroud)

以便:

>>> Fruits.orange == Colors.orange
False
Run Code Online (Sandbox Code Playgroud)

而且我们不再生活在一些颜色是您可以在当地杂货店的产品部分找到的东西的世界.


Aus*_*sye 13

如果其他人发现自己在我们之后来到这里,我们也遇到了同样的问题。我们能够将其追溯到绝对进口和相对进口的无意混合,其方式类似于下面描述的情况。

# File: package/module/analysis_types.py
Analysis = enum.Enum("Analysis", "static dynamic")
Run Code Online (Sandbox Code Playgroud)
# File: package/module/static_thing.py
from .analysis_types import Analysis

class StaticThing:
    ...
    analysis = Analysis.static
    ...
Run Code Online (Sandbox Code Playgroud)
# File: package/module/static_thing_test.py
from package.module.static_thing import StaticThing
from .analysis_types import Analysis

# This throws an AssertionError because as
#  id(StaticThing.analysis) != id(Analysis.static)
assert StaticThing.analysis == Analysis.static
Run Code Online (Sandbox Code Playgroud)

通过以下更改恢复了预期行为:

# File: package/module/static_thing_test.py
from .static_thing import StaticThing
from .analysis_types import Analysis

# This does NOT throw an AssertionError because as
#  id(StaticThing.analysis) == id(Analysis.static)
assert StaticThing.analysis == Analysis.static
Run Code Online (Sandbox Code Playgroud)

  • 绝对是导入加载/重新加载问题。我遇到了这个问题,我的特殊问题不是在测试中,而是使用了“%aut​​oreload”魔法的笔记本。解决办法就是停止使用那个魔法。 (3认同)