在Python中何时使用'is'关键字?

13 投票
3 回答
3714 浏览
提问于 2025-04-18 01:30

今天我学习了Python中的is关键字,并尝试了以下内容:

>>> x=2+2
>>> y=4
>>> x is y
True

我一开始用整数来测试is,因为我知道结果应该是False,所以结果让我感到很惊讶!为了给大家一些背景,我之前的编程经验主要是C++和C#,在那两种语言中,值类型和对象类型是有区别的。而在Python中,我现在意识到,所有东西都是引用类型。

看起来x is y返回True的原因和这个问题中解释的一样,Python中的'is'关键字是如何实现的?,这和用is比较字符串有关。也就是说,运行时环境通过共享或“驻留”整数来节省内存,就像它对待字符串一样——这个在另一个问题的回答中有更详细的解释:Python的“is”运算符在处理整数时表现得很意外,这是我在最初发帖后发现的。

我还发现另一个令人惊讶的事情是,is返回的值是依赖于实现的。这和我主要的问题有关。在关于is在字符串方面实现的参考问题中,有一些讨论关于何时使用is,有几个用户表示他们几乎从不使用它。所以我的问题是,什么时候应该使用is关键字?有没有一些经典的例子或一般的规则?

3 个回答

2

首先,x 是 y 为 True 的原因和这个问题中解释的内容一样吗?这个问题是关于在 Python 中如何使用 'is' 关键字,特别是与字符串相关的。

其实是有点相似的。在 Python 中,整数范围从 -5256 的这些数字是被缓存的。这是为了提高性能。

那么我的问题是,什么时候应该使用 is 这个关键字呢?

你可以用 is 来检查两个引用是否指向同一个对象(它检查的是对象的身份)。另外,当你要把一个对象的引用和 None 进行比较时,推荐使用 is

if some_object is None:
    # ...
17

is 是用来检查身份的,不是用来检查相等的。这意味着 Python 只是比较对象所在的内存地址。”

有一个简单的规则可以帮助你判断什么时候用 ==,什么时候用 is。

  • == 是用来检查值是否相等的。当你想知道两个对象的值是否相同时,就用它。
  • is 是用来检查引用是否相等的。当你想知道两个引用是否指向同一个对象时,就用它。

一般来说,当你比较某个简单类型时,通常是在检查值是否相等,所以你应该使用 ==。

如果两个变量指向同一个对象,is 会返回 True;如果变量指向的对象值相等,== 会返回 True。

>>> a = [1, 2, 3]
>>> b = a
>>> b is a 
True
>>> b == a
True
>>> b = a[:]
>>> b is a
False
>>> b == a
True

第二个测试之所以有效,是因为 Python 会缓存小整数对象,这属于实现细节。对于较大的整数,这种方法就不管用了:

>>> 1000 is 10**3
False
>>> 1000 == 10**3
True
The same holds true for string literals:

>>> "a" is "a"
True
>>> "aa" is "a" * 2
True
>>> x = "a"
>>> "aa" is x * 2
False
>>> "aa" is intern(x*2)
True

注意: “由于自动垃圾回收、空闲列表和描述符的动态特性,你可能会在某些使用 is 操作符的情况下看到看似不寻常的行为,比如涉及实例方法或常量的比较。”

由于 CPython 的引用实现方式,如果你错误地使用 is 来比较整数的引用相等性,你会得到意想不到和不一致的结果:

>>> a = 500
>>> b = 500
>>> a == b
True
>>> a is b
False

这基本上符合我们的预期:a 和 b 的值相同,但它们是不同的实体。那么这个呢?

>>> c = 200
>>> d = 200
>>> c == d
True
>>> c is d
True

这与之前的结果不一致。发生了什么?原来 Python 的引用实现会将范围在 -5 到 256 之间的整数对象缓存为单例实例,以提高性能。这里有个示例来演示这一点:

>>> for i in range(250, 260): a = i; print "%i: %s" % (i, a is int(str(i)));
... 
250: True
251: True
252: True
253: True
254: True
255: True
256: True
257: False
258: False
259: False

这也是不应该使用 is 的另一个明显原因:当你错误地将其用于值相等性时,行为会依赖于具体的实现。

20

当你想知道两个对象是否是同一个对象时,应该使用 is。如果你只是想知道两个对象的值是否相同,就不要用它。

有一个经典的例子,但这个例子其实帮助不大。人们会告诉你,检查 None 值时应该用 x is None,而不是 x == None。不过,这两者之间实际上差别不大。(想了解更多,可以查看这个问题。)

在某些情况下,你可能会创建一些值相同但却是不同对象的东西。比如,你可以想象一个幻想战争游戏,玩家可以魔法般地创造小兵来与对手作战。于是,玩家可能会创造100个一模一样的兽人。每个兽人可以用一个对象来表示,它们在属性上是相同的,但实际上是100个不同的对象。现在,如果对手试图对其中一个兽人施放“火球”法术,而玩家在同一回合对另一个兽人施放“防火”法术,你可能想检查火球法术的目标是否 is 防护法术的目标。因为所有的兽人都是相等的,仅仅用相等的方式检查是不够的,只有特定的一个兽人才是每个法术的目标,而你想知道这两个目标是否是同一个对象。这个例子虽然有点牵强,但可以让你大致明白在什么情况下你可能会用到 is

撰写回答