如何通过区分类型来隔离枚举?

4
以下代码定义了两个枚举类型。
class Insect:
    BEE = 0x00
    WASP = 0x01
    BUMBLEBEE = 0x02


class Breakfast:
    HAM = 0x00
    EGGS = 0x01
    PANCAKES = 0x02


b = Insect.WASP
if b == Breakfast.EGGS:
    print("ok")

如上所述,一个人很容易犯错,测试不同的枚举值。如何将枚举值隔离,而不是按不同的值隔离,以便上面的测试会生成错误?
更新
我看到这是从 Python 2 迁移到 Python 3 的道路上的细节之一。
感谢 wim 的建议,下面的代码将在我尝试比较苹果和橙子时生成一个错误。
from enum import Enum


class Apple(Enum):
    RED_DELICIOUS = 0x00
    GALA = 0x01
    FUJI = 0x02

    def __eq__(self, other):
        if type(other) is not type(self):
            raise Exception("You can't compare apples and oranges.")
        return super().__eq__(other)


class Orange(Enum):
    NAVEL = 0x00
    BLOOD = 0x01
    VALENCIA = 0x02

    def __eq__(self, other):
        if type(other) is not type(self):
            raise Exception("You can't compare apples and oranges.")
        return super().__eq__(other)


apple = Apple.GALA
if apple == Orange.BLOOD:
    print("ok")

2
你没有创建一个“枚举”,而是创建了两个带属性的类。在3.4+中,可以使用enum.Enum类型创建枚举,或者在3.3-中使用enum34回溯,或者在2和3中使用高级枚举库。(声明:这三个库都是我编写的。) - Ethan Furman
2个回答

7
不要使用自定义类来处理它。使用stdlib的枚举类型,它们会在这里做正确的事情。
from enum import Enum

class Insect(Enum):
    ...

如果你想要一个硬件崩溃:

class MyEnum(Enum):

    def __eq__(self, other):
        if type(other) is not type(self):
            raise Exception("Don't do that")
        return super().__eq__(other)

但我建议不要采用这种设计,因为:

  1. 枚举实例通常是按标识比较而不是按相等性比较的
  2. 在Python中,很少(甚至没有?)出现相等比较引发错误的先例

在相等测试失败时引发异常几乎从来都不是一个好主意。== 应该返回 TrueFalse,而不是引发异常。 - Ethan Furman
2
我同意您的设计建议,但问题被标记为 type-safety,并且明确要求“*...以便上面的测试将 生成一个错误*”。 - wim
啊,我错过了。不过谢谢你把我的回答加入到你的答案中。 :) - Ethan Furman

3
关于相等性测试,为什么不应该引发异常,以及正确的类型测试方法。
为什么不应该使用“==”引发异常?
在Python中,特别是在容器中(如列表、字典和集合)中,常常使用相等性测试来查找成员、返回成员、更改成员、删除成员等。如果您的Apple枚举每次与非Apple进行比较时都会引发异常,它将破坏添加到任何容器中的功能。
自定义类型失败相等测试的正确方法(以及其他比较测试):
def __eq__(self, other):
    if not isinstance(other, self.__class__):
        return NotImplented   # note:  NOT RAISE
    ... comparison here ...

注意:上述测试已经内置在Enum类型中。

正确的类型测试

如果您真的非常希望确保不会得到不想要的类型,并且错误应该是结果:

var1 = ...
if not isinstance(var1, SomeTypeHere):
    raise SomeException

但是上述代码不应该出现在任何丰富比较方法*中。


* 丰富比较方法包括__eq____ne____ge____gt____le____lt__


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接