python - 为什么 `if None.__eq__("a")` 似乎评估为 True(但不完全)?

标签 python python-3.x string boolean-expression equivalence

如果您在 Python 3.7 中执行以下语句,它将(根据我的测试)打印 b:

if None.__eq__("a"):
    print("b")

但是,None.__eq__("a") 的计算结果为 NotImplemented

自然,"a".__eq__("a") 的计算结果为 True"b".__eq__("a") 计算结果为 False

我最初在测试函数的返回值时发现了这一点,但在第二种情况下没有返回任何内容——因此,该函数返回了 None

这是怎么回事?

最佳答案

这是一个很好的例子,说明为什么不应直接使用 __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 NotImplemented

class B:
    def __eq__(self, other):
        print('B.__eq__')
        return NotImplemented

class C:
    def __eq__(self, other):
        print('C.__eq__')
        return True

a = A()
b = B()
c = C()

print(a == b)
# A.__eq__
# B.__eq__
# False

print(a == c)
# A.__eq__
# C.__eq__
# True

print(c == a)
# C.__eq__
# True

当然,这并不能解释为什么该操作返回 true。这是因为 NotImplemented 实际上是一个真值:

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

同,

bool(NotImplemented)
# True

有关哪些值被认为是真值和假值的更多信息,请参阅 Truth Value Testing 上的文档部分,以及 this answer .值得注意的是,NotImplemented 是真实的,但如果类定义了返回的 __bool____len__ 方法,情况就不同了False0 分别。


如果您想要 == 运算符的等效功能,请使用 operator.eq :

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

但是,如前所述,对于 此特定场景,您正在检查 None,请使用 is:

var = 'a'
var is None
# False

var2 = None
var2 is None
# True

与此功能等效的是使用 operator.is_ :

operator.is_(var2, None)
# True

None 是一个特殊的对象,在任何时间点内存中只存在一个版本。 IOW,它是 NoneType 类的唯一单例(但同一个对象可能有任意数量的引用)。 PEP8 guidelines明确说明:

Comparisons to singletons like None should always be done with is or is not, never the equality operators.

总之,对于像 None 这样的单例,使用 is 进行引用检查更合适,尽管 ==is 可以正常工作。

关于python - 为什么 `if None.__eq__("a")` 似乎评估为 True(但不完全)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53984116/

相关文章:

python - Python 中 NOT、AND、OR 的逻辑运算符的优先级(运算顺序)

python - 从 Linux centos 7.0 终端而不是从 python 控制台运行时的 os.makedirs 问题

c++ - 从 Python 使用 C++? (不是提升)

python - 安装程序应该是本地项目的路径或以 svn+、git+、hg+ 或 bzr+ 开头的 VCS url

python - 如何保留列表中的第 n 个项目并使其余项目为零

python-3.x - 如果关联 ID 的一部分匹配,则来自多行的平均值

c# - 日志记录的扩展方法。一个好主意?

R strip拆分数据框中的一列

java - 如何比较字符串和 Hashmap 键?

python - 对多个符号变量使用 Lambdify