根据文档enum members are singletons。
>>> from enum import Enum
>>> class Potato(Enum):
... spud = 1234
... chat = 1234
...
>>> x = 1234
>>> y = 1234
>>> x is y
False
>>> x = Potato.spud
>>> y = Potato.chat
>>> x is y
True
>>> x.value is y.value
True
这是否意味着我们也应该通过身份来比较它们,就像PEP8建议我们应该总是使用的是/不是,而且从来都不是单身操作者,例如None"?
到目前为止,我一直在使用平等运营商,并且没有发现任何问题需要保证如PEP8警告的强烈措辞。如果有的话,为枚举实例使用相等的缺点到底是什么?或者它只是一个微优化?
答案 0 :(得分:8)
来自https://docs.python.org/3/library/enum.html#module-enum:
在枚举中,成员可以通过身份进行比较
特别是来自https://docs.python.org/3/library/enum.html#comparisons:
枚举成员按身份进行比较
答案 1 :(得分:4)
首先,我们绝对可以排除x.value is y.value
,因为那些不是单身人士,这些都是您存储在属性中的普通价值。
但是x is y
呢?
首先,我认为,通过"像无和#34;这样的单身人士,PEP 8特别指的是一些小的,固定的内置单例,就像None
一样重要。什么重要的方式?您为什么要将None
与is
进行比较?
可读性:if foo is None:
读起来就像它的意思。在极少数情况下,当您想要将True
与其他真实值区分开来时,if spam is True:
读取的内容优于if spam == True:
,并且更明显地表明这不是一件轻浮的事情== True
被不正确地遵循Python中的C ++编码标准的人使用。这可能适用于foo is Potato.spud
,但不适用于x is y
。
用作哨兵:None
用于表示"值丢失"或"搜索失败"或类似的情况。当然,在None
本身可以是值的情况下,它不应该被使用。如果有人创建了一个实例比较等于None
的类,那么在没有意识到的情况下可能会遇到这个问题。 is None
可以防范这种情况。由于True
和False
,1 == True
和0 == False
(在极少数情况下,当你想区分它们时)更是一个问题。这个原因似乎不适用于此处 - 如果1 == Potato.spud
,那只是因为您有意选择使用IntEnum
而不是Enum
,在这种情况下,&None
#39;正是你想要的......
(准)关键字状态:None
和朋友们多年来逐渐从完全正常的内置关键字迁移到关键字。符号None
的默认值不仅仅是单例,唯一的可能的值就是单例。这意味着优化器,静态linter等可以假设is
在代码中的含义,以及它在运行时定义的任何方式。同样,这个原因似乎并不适用。
表现:这根本不是考虑因素。在某些实现中,与==
进行比较而不是if devo is Potato.spud:
进行比较可能会更快,但这实际上不太可能在实际代码中产生差异(或者,如果确实如此,实际代码可能需要更高级别的优化,例如将列表转换为集合......)。
那么,结论是什么?
嗯,这里很难摆脱意见,但我认为这样说是合理的:
if x is y:
是合理的,如果它使事情更具可读性,但只要你在代码库中保持一致,我就不会认为任何人都会抱怨。Potato
,即使他们都知道是if x.value is Potato.spud.value
个对象,也是不合理的。答案 2 :(得分:2)
PEP 8说:
应该始终使用
is
或is not
来比较像None这样的单例,而不是等式运算符。
我不赞同abarnert:这不是因为这些是内置的或特殊的以任何方式。这是因为在这些情况下你关心 对象,而不是看起来像它的东西。
例如,当您使用is None
时,您关心的是它是否 None
,而不是None
}已经过去了。这在实践中可能很难(毕竟只有一个None
但是它确实有点重要。
举个例子:
no_argument = object()
def foo(x=no_argument):
if x OP no_argument:
...
...
如果OP
为is
,则这是完全惯用的代码。如果它是==
,那就不是。
出于同样的原因,你应该这样做:
如果你想要对鸭子类型进行相等,例如使用IntEnum
或你想要进行子类化和覆盖的枚举(例如当你有方法和其他附加功能的复杂枚举类型时)它会使感觉使用==
。
当您使用枚举作为愚蠢的哨兵时,请使用is
。