为什么原始类型不使用“比较”代替“ ==”?

时间:2019-05-21 22:48:07

标签: python comparison immutability primitive-types

当我使用Pytest进行Python格式化时,它抱怨做类似的事情:

>>> assert some_function_ret_val() == True
E712 comparison to True should be 'if cond is True:' or 'if cond:'

并希望:

assert some_function_ret_val() is True

我知道只能有一个True / False / None副本,但是我认为所有原语都是不可变的类型。

在什么情况下原始类型的“ ==”和“ is”比较会不同?

否则,为什么“ ==”成为比较任务中的常态?

我发现了这个stackoverflow帖子,它讨论了与非原始类型的比较,但是我似乎找不到找到为什么“是”比较可能与原始类型进行比较危险的原因。 Comparison with boolean numpy arrays VS PEP8 E712

如果只是约定俗成,我会认为“是”比“ ==”更易读,但我觉得可能存在一些疯狂的情况,其中可能有多个原始类型的副本。 >

1 个答案:

答案 0 :(得分:3)

Python没有基本类型。 Python中的所有内容都是一个对象。

通常,您唯一应该使用is的地方是在语言保证的单例上,例如TrueFalseNone,或者说,出于调试目的,您真的想检查对象身份。

在其他每种情况下,如果您使用is表示相等,则将依赖实现细节和特定于实现的优化(例如,窥孔优化器和字符串插入)。等式运算符为==,在这些情况下应使用。尽管通常,Python解释器会优化不可变的类型,但当您指的是平等时,您仍不应依赖身份,因为多数情况下这不是语言保证

例如,在CPython 3.7上,您可以“安全地” 尝试使用is比较小整数,因为它们被缓存了,这是实施细节,应该依赖。在Python 3.9中或任何时候都可以自由更改。另外,请参阅@ user2357112的评论,它对于缓存的小整数甚至还不一定安全!

同样,它仅适用于小整数[-5,256],因此:

>>> def add(a, b): return a + b
...
>>> 16 is add(8, 8)
True
>>> 1000 is add(500, 500)
False

注意,我将实际加法放入函数中,解释器经常优化不可变文字和算术表达式:

>>> 1000 is (500 + 500)
True

但是现在显而易见,为什么您不能依靠它。

另一个适合使用is进行“相等”比较的示例是比较enum类型,这些类型是有保证的单例:

import enum
class Color(enum.Enum):
    RED = 1
    BLUE = 2

RED = Color.RED
BLUE = Color.BLUE

print(Color(1) is RED)