Python 枚举实例是否应按标识或相等进行比较?
根据文件 这是否意味着我们也应该通过身份来比较它们,正如PEP8所建议的那样,我们应该始终使用是/不是,并且永远不要使用“Singleton like None”的相等运算符Python 枚举实例是否应按标识或相等进行比较?,python,enums,Python,Enums,根据文件 这是否意味着我们也应该通过身份来比较它们,正如PEP8所建议的那样,我们应该始终使用是/不是,并且永远不要使用“Singleton like None”的相等运算符 到目前为止,我一直在使用相等运算符,并没有注意到与此相关的任何问题,以保证像PEP8警告的那样使用强有力的措辞。对枚举实例使用相等性(如果有的话)的缺点到底是什么?或者这只是一个微观优化?首先,我们可以明确排除x.value是y.value,因为它们不是单例,它们是存储在属性中的非常普通的值 但是x是y呢 首先,我认为,P
到目前为止,我一直在使用相等运算符,并没有注意到与此相关的任何问题,以保证像PEP8警告的那样使用强有力的措辞。对枚举实例使用相等性(如果有的话)的缺点到底是什么?或者这只是一个微观优化?首先,我们可以明确排除
x.value是y.value
,因为它们不是单例,它们是存储在属性中的非常普通的值
但是x是y呢
首先,我认为,PEP 8所说的“像无一样的单例”,是指一小部分固定的内置单例,它们在某些重要方面像无一样。什么是重要的方式?为什么要将None
与is
进行比较
可读性:如果foo为None:
的内容与它的意思相同。在您想区分代码> >真/代码>与其他真实值的情况下,<代码>如果垃圾邮件是真的:读取优于<代码>如果SPAM=true:<代码>,并且更明显地表明,这不是一个轻率的<代码> = =真/ <代码>,这是某人不正确地遵循Python中的C++编码标准所使用的。这可能适用于foo is Potato.spud
,但在x is y
中不太适用
用作哨兵:None
用于表示“缺少值”或“搜索失败”或类似情况。当然,在None
本身可以是值的情况下不应该使用它。如果有人创建了一个实例比较等于None
的类,那么可能会在没有意识到的情况下遇到这个问题<代码>为无可防止出现这种情况。这对于True
和False
(同样,在您想要区分它们的罕见情况下)来说是一个更大的问题,因为1==True
和0==False
。如果1==Potato.spud
,这个原因在这里似乎不适用,这只是因为您有意选择使用IntEnum
而不是Enum
,在这种情况下,这正是您想要的
(准)关键字状态:None
,多年来,好友已逐渐从完全正常的内置项迁移到关键字。符号None
的默认值不仅始终是singleton,唯一可能的值是singleton。这意味着优化器、静态linter等可以对None
在代码中的含义进行假设,而在运行时定义的任何内容都不能这样做。同样,这个理由似乎并不适用
性能:这根本不是一个考虑因素。在某些实现中,与is
相比,它可能比=
更快,但这不太可能对实际代码产生任何影响(或者,如果确实如此,则实际代码可能需要更高级别的优化,如将列表转换为集合……)
那么,结论是什么
好吧,在这里很难摆脱一种观点,但我认为这样说是合理的:
是合理的,如果它能让事情更可读,但只要你在代码库中保持一致,我认为任何人都不会抱怨如果devo是土豆。spud:
,即使它们都是如果x是y:
对象,也是不合理的
是不合理的如果x.value是Potato.spud.value
is
或is not
进行与None等单例的比较,切勿使用相等运算符
我不同意abarnert的观点:这并不是因为它们是内置的或在任何方面都是特殊的。这是因为在这些情况下,你关心的是对象,而不是看起来像它的东西
例如,使用is None
时,您关心的是您放在那里的None
,而不是传入的其他None
。这在实践中可能很困难(毕竟只有一个无),但有时确实很重要
例如:
no_argument = object()
def foo(x=no_argument):
if x OP no_argument:
...
...
如果OP
是is
,则这是完全惯用的代码。如果它是==
,则不是
出于同样的原因,您应做出如下决定:
- 如果您希望使用相等于duck类型,例如使用
IntEnum
或您可能希望子类化和覆盖的枚举(例如,当您使用带有方法和其他附加项的复杂枚举类型时),则使用=
是有意义的
- 将枚举用作哑哨兵时,请使用
is
来自:
在枚举中,可以按标识比较成员
特别是:
枚举成员按标识进行比较
请记住,Enum
只是在3.4中添加的,PEP 8没有被重写;除非有人发出臭味(在bug跟踪器或-dev
或-ideas
列表上),否则它只会得到少量编辑。它甚至不建议在需要枚举时使用Enum
。如果垃圾邮件是真的
也可以避免True==1
@user2357112什么时候会出现这种情况?@Veedrac:不经常,但是我们已经假设我们处于需要将True
与布尔上下文中被认为是True的其他值区分开来的情况。对于那些其他数值来说,这并不是一个很大的延伸。也许在诸如实现某种通用JSON处理的情况下,您需要以不同的方式处理布尔值和数字,这可能很重要。@user2357112:同意,事实上,我怀疑区分是真的<
no_argument = object()
def foo(x=no_argument):
if x OP no_argument:
...
...