当我使用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
如果只是约定俗成,我会认为“是”比“ ==”更易读,但我觉得可能存在一些疯狂的情况,其中可能有多个原始类型的副本。 >
答案 0 :(得分:3)
Python没有基本类型。 Python中的所有内容都是一个对象。
通常,您唯一应该使用is
的地方是在语言保证的单例上,例如True
,False
和None
,或者说,出于调试目的,您真的想检查对象身份。
在其他每种情况下,如果您使用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)