为什么不使用 "is" 比较来代替基本类型的“==”?
Why isn't "is" comparison used in place of "==" for 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"比较原始类型会有所不同?
否则,为什么“==”成为比较任务的常态?
我发现这个 Whosebug post 讨论了与非原始类型的比较,但我似乎无法找到为什么 "is" 比较对原始类型可能很危险的原因。
Comparison with boolean numpy arrays VS PEP8 E712
如果只是约定俗成,我会认为 "is" 比“==”更易读,但我觉得可能会有一些疯狂的边缘情况,其中可能有多个原语副本类型。
Python 没有原始类型。 Python 中的所有内容都是对象。
通常,您唯一应该使用 is
的地方是 language-guaranteed 单例,例如 True
、False
和 None
或者说出于调试目的,您实际上想要检查对象身份。
在所有其他情况下,如果您使用 is
表示相等(例如 peep-hole 优化器和字符串驻留)。相等运算符是 ==
,应该在这些情况下使用。虽然 Python 解释器通常会优化不可变类型,但当您表示相等时,您仍然不应依赖标识,因为大多数情况下,这不是 语言保证.
例如,在 CPython 3.7 上,您可以 "safely" 忍不住选择使用 is
来比较 小整数 因为它们被缓存了,所以这是一个实现细节,应该不 依赖。这可以在 Python 3.9 或任何时候自由更改。另外,请参阅@user2357112 关于缓存的小整数甚至不一定安全的评论!重申一下:这不是语言保证 - 它是如何实施的 side-effect。
同样,它只适用于小整数,[-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
进行 "equalityish" 比较的例子是比较 enum
类型,保证是单例:
import enum
class Color(enum.Enum):
RED = 1
BLUE = 2
RED = Color.RED
BLUE = Color.BLUE
print(Color(1) is RED)
当我使用 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"比较原始类型会有所不同?
否则,为什么“==”成为比较任务的常态?
我发现这个 Whosebug post 讨论了与非原始类型的比较,但我似乎无法找到为什么 "is" 比较对原始类型可能很危险的原因。 Comparison with boolean numpy arrays VS PEP8 E712
如果只是约定俗成,我会认为 "is" 比“==”更易读,但我觉得可能会有一些疯狂的边缘情况,其中可能有多个原语副本类型。
Python 没有原始类型。 Python 中的所有内容都是对象。
通常,您唯一应该使用 is
的地方是 language-guaranteed 单例,例如 True
、False
和 None
或者说出于调试目的,您实际上想要检查对象身份。
在所有其他情况下,如果您使用 is
表示相等(例如 peep-hole 优化器和字符串驻留)。相等运算符是 ==
,应该在这些情况下使用。虽然 Python 解释器通常会优化不可变类型,但当您表示相等时,您仍然不应依赖标识,因为大多数情况下,这不是 语言保证.
例如,在 CPython 3.7 上,您可以 "safely" 忍不住选择使用 is
来比较 小整数 因为它们被缓存了,所以这是一个实现细节,应该不 依赖。这可以在 Python 3.9 或任何时候自由更改。另外,请参阅@user2357112 关于缓存的小整数甚至不一定安全的评论!重申一下:这不是语言保证 - 它是如何实施的 side-effect。
同样,它只适用于小整数,[-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
进行 "equalityish" 比较的例子是比较 enum
类型,保证是单例:
import enum
class Color(enum.Enum):
RED = 1
BLUE = 2
RED = Color.RED
BLUE = Color.BLUE
print(Color(1) is RED)