Python中的枚举无法正常工作

问题描述 投票:6回答:2

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

from enum import Enum
Analysis = Enum('Analysis', 'static dynamic')

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

class Step:
    def __init__(self):
        self.analysis = None
        self.bcs = []

到目前为止非常简单,所以当我在列表中有几个步骤时,我会尝试查看枚举类型,并且它已正确分配。但是它们并不相等:

# 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()

打印

{'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

这是不正确的,但是我不知道如何调试它。

UPDATE

根据@martineau的建议,我改为创建了一个IntEnum,这解决了我的问题。但是,我不明白为什么正常的Enum无法正常工作。

python python-3.x enums enumeration
2个回答
13
投票

在评论中,您说:

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

如果我对您的理解正确,您是说每次添加新步骤时都会创建一个新的Enum对象。这可能就是为什么您看到“ bug”的原因。尽管两个不同的Enum对象的名称和顺序相同,但它们的值不一定相等。例如:

import enum
Analysis1 = enum.Enum("Analysis", "static dynamic")
Analysis2 = enum.Enum("Analysis", "static dynamic")

但是:

>>> Analysis1.static == Analysis2.static
False

这是因为据我所知,没有为Enum对象定义相等运算符,所以使用了检查id的默认行为。

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

import enum
Analysis1 = enum.IntEnum("Analysis", "static dynamic")
Analysis2 = enum.IntEnum("Analysis", "static dynamic")

然后:

>>> Analysis1.static == Analysis2.static
True

为什么有Enum IntEnum

乍看之下IntEnum似乎是[[总是我们想要的。那么Enum的意义是什么?

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

Fruits = enum.IntEnum("Fruits", "orange apple lemon") Colors = enum.IntEnum("Colors", "orange red blue")

但是现在:

>>> Fruits.orange == Colors.orange True

但是,从哲学上讲,“橙色”(水果)与“橙色”(颜色)不同!我们不应该能够区分两者吗?此处,intIntEnum子类对我们不利,因为Fruits.orangeColors.orange都等于1。当然,正如我们在上面看到的,比较Enum s是比较id s,而不是值。由于Fruits.orangeColors.orange是唯一的对象,因此它们的比较不相等:

Fruits = enum.Enum("Fruits", "orange apple lemon") Colors = enum.Enum("Colors", "orange red blue")

因此:

>>> Fruits.orange == Colors.orange False

而且我们不再生活在一个可以在当地杂货店的农产品部分找到某些颜色的东西的世界中。

0
投票
如果其他人发现我们之后出现在我们这里,我们也会遇到同样的问题。我们能够以类似于以下所述的方式将其追溯到绝对进口和相对进口的无意混合。

# File: package/module/analysis_types.py Analysis = enum.Enum("Analysis", "static dynamic")

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

class StaticThing:
    ...
    analysis = Analysis.static
    ...
# 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(StaticThink.analysis) != id(Analysis.static)
assert StaticThink.analysis == Analysis.static
通过以下更改恢复了预期的行为:

# 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(StaticThink.analysis) == id(Analysis.static) assert StaticThink.analysis == Analysis.static

© www.soinside.com 2019 - 2024. All rights reserved.