首页 论坛 置顶 在Python中过度使用“is”而非“==”的风险

正在查看 1 个帖子:1-1 (共 1 个帖子)
  • 作者
    帖子
  • #24015

    如果你已经使用Python一段时间了,可能在代码中使用过is==。它们看起来相似,读起来也很像。但在底层,它们的功能却截然不同。当你本意是使用==时却使用了is,可能会导致微妙而棘手的错误,这些错误非常难以追踪。

    is==之间有什么区别?

    • == 检查两个值是否相等。
    • is 检查两个变量是否指向内存中的同一个对象。

    这里有一个简单的方法来记住它:

    👉 == → “这些东西看起来一样吗?”

    👉 is → “这些东西真的是同一个对象吗?”

    快速示例

    a = [1, 2, 3]
    b = [1, 2, 3]
    
    print(a == b)  # True: 内容相同
    print(a is b)  # False: 内存中的对象不同

    尽管 ab 包含相同的列表值,但它们不是同一个对象。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 还缓存了介于 -5256 之间的小整数。

    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

    但即使对于 TrueFalse,在数据密集型代码(例如 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

正在查看 1 个帖子:1-1 (共 1 个帖子)
  • 哎呀,回复话题必需登录。