首页 › 论坛 › 置顶 › 在Python中过度使用“is”而非“==”的风险
-
作者帖子
-
2025-05-28 11:54 #24015Q QPY课程团队管理员
如果你已经使用Python一段时间了,可能在代码中使用过
is
和==
。它们看起来相似,读起来也很像。但在底层,它们的功能却截然不同。当你本意是使用==
时却使用了is
,可能会导致微妙而棘手的错误,这些错误非常难以追踪。is
和==
之间有什么区别?==
检查两个值是否相等。is
检查两个变量是否指向内存中的同一个对象。
这里有一个简单的方法来记住它:
👉 == → “这些东西看起来一样吗?”
👉
is
→ “这些东西真的是同一个对象吗?”快速示例
a = [1, 2, 3] b = [1, 2, 3] print(a == b) # True: 内容相同 print(a is b) # False: 内存中的对象不同
尽管
a
和b
包含相同的列表值,但它们不是同一个对象。Python 创建了两个独立的列表。危险的地方
问题出现在开发者假设
is
的行为与==
相同,或反之,尤其是因为有时is
由于 Python 的内部优化而“意外”工作。示例 1:字符串
x = "hello" y = "hello" print(x == y) # True
print(x is y) # True? ...有时是
对于
is
来说,这可能是True
,因为 Python 会“驻留”(重用)短字符串以节省内存。但请看这个:a = "hello world! this is a very long string" b = "hello world! this is a very long string"
print(a == b) # True print(a is b) # False
突然间,
is
不再有效,尽管字符串是相等的。为什么?因为 Python 没有对较长的字符串进行驻留。在这里依赖is
会导致不稳定、不一致的结果,这些结果取决于你无法控制的因素,比如字符串长度或 Python 实现。示例 2:整数
Python 还缓存了介于
-5
和256
之间的小整数。x = 256 y = 256 print(x is y) # True a = 257 b = 257 print(a is b) # False
编写一些“通过”某些测试但在生产环境中失败的代码是很容易的。这些错误在后期调试时几乎是不可能的。
那么,什么时候应该使用
is
?使用
is
是有其合理用途的。但这些用途是特定且罕见的。在检查单例对象时使用
is
例如:
if my_var is None: ...
这是检查
None
的正确方式,因为None
是一个单例。在 Python 中只有一个None
对象。其他有效的情况:
-
my_obj is True
-
my_obj is False
但即使对于
True
和False
,在数据密集型代码(例如 pandas、NumPy)中,使用==
通常更安全,因为这些库重新定义了什么是“真值”。真实世界的错误场景
以下是我见过的一些真实错误:
错误 1:循环中的错误比较
for item in my_list: if item is "done": # 哎呀
这可能对某些字符串有效,但对其他字符串则会静默失败。正确的检查是:
for item in my_list: if item == "done": break
错误2:数据验证中的假阴性
user_input = input("请输入 yes 或 no: ") if user_input is "yes": # 即使输入为 'yes' 也可能失败 print("确认!")
你可能永远不会知道这个失败,除非你的用户输入
"yes"
但没有任何反应。错误 3:不可靠的条件逻辑
x = 1000 y = 10 * 100
if x is y: # 错误!即使值相同
do_something()这将静默地不执行
do_something()
,即使大多数人会说“1000等于1000。”何时使用哪一个?
- 除非你100%确定是在检查身份,否则请使用
==
。 - 仅在检查
None
或与哨兵对象比较时使用is
。 - 不要依赖Python的内部优化,如字符串驻留或小整数缓存。这些是实现细节,可能在不同版本或平台之间发生变化。
操作 使用 ==
?使用 is
?值相等 ✅ ❌ 对象身份 ❌ ✅ 与 None
比较❌ ✅ 与常量比较(例如,字符串,整数) ✅ ❌ 编写可靠、可移植的代码 ✅ ❌(除了 None
) -
作者帖子
- 哎呀,回复话题必需登录。