为什么`if None .__ eq __(“ a”)`似乎评估为True(但不完全)?

为什么`if None .__ eq __(“ a”)`似乎评估为True(但不完全)?,第1张

为什么`if None .__ eq __(“ a”)`似乎评估为True(但不完全)?

这是一个很好的例子,说明为什么

__dunder__
不应该直接使用这些方法,因为它们通常不是等效 *** 作符的适当替代;您应该使用
==
运算符来代替相等性比较,或者在这种特殊情况下,当检查
None
,请使用
is
(跳至答案的底部以获取更多信息)。

你做完了

None.__eq__('a')# NotImplemented

NotImplemented
由于要比较的类型不同,返回的结果不同。考虑另一个示例,其中以这种方式比较了具有不同类型的两个对象,例如
1
'a'
。这样做
(1).__eq__('a')
也不正确,并且会返回
NotImplemented
。比较这两个值是否相等的正确方法是

1 == 'a'# False

这里发生的是

  1. 首先,
    (1).__eq__('a')
    尝试,然后返回
    NotImplemented
    。这表明不支持该 *** 作,因此
  2. 'a'.__eq__(1)
    被调用,它也返回相同的
    NotImplemented
    。所以,
  3. 将对象视为不相同,然后
    False
    将其返回。

这是一个不错的小MCVE,它使用一些自定义类来说明这种情况:

class A:    def __eq__(self, other):        print('A.__eq__')        return NotImplementedclass B:    def __eq__(self, other):        print('B.__eq__')        return NotImplementedclass C:    def __eq__(self, other):        print('C.__eq__')        return Truea = A()b = B()c = C()print(a == b)# A.__eq__# B.__eq__# Falseprint(a == c)# A.__eq__# C.__eq__# Trueprint(c == a)# C.__eq__# True

当然,这并不能解释 为什么 该 *** 作返回true。这是因为

NotImplemented
实际上是一个真实值:

bool(None.__eq__("a"))# True

和…一样,

bool(NotImplemented)# True

有关什么值被认为是真实和虚假的更多信息,请参阅真值测试的文档部分以及此答案。值得注意的是,这里

NotImplemented
是truthy,但它会是一个不同的故事有类中定义一个
__bool__
__len__
方法返回
False
0
分别。


如果要

==
使用与运算符等效的功能,请使用
operator.eq

import operatoroperator.eq(1, 'a')# False

但是,如前所述,对于要检查的 特定情况 ,请

None
使用
is

var = 'a'var is None# Falsevar2 = Nonevar2 is None# True

其功能等效项是使用

operator.is_

operator.is_(var2, None)# True

None
是一个特殊对象,并且在任何时间内存中只有1个版本。IOW,它是类的唯一单例
NoneType
(但是同一对象可以具有任意数量的引用)。该PEP8方针更加明确:

与单例之类的比较

None
应始终使用
is
is not
,而不应使用相等运算符。

综上所述,对于单身人士喜欢

None
,与基准检查
is
是比较合适的,虽然两者
==
is
会工作得很好。



欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5654330.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-16
下一篇2022-12-16

发表评论

登录后才能评论

评论列表(0条)

    保存