你真的了解Python的is和==区别?

下面有段代码(以下简称测试例子),你能在不看答案情况下知道运行结果吗?

a = 1
b = 1
print(a is b) # True
print(a == b) # True
a = 10000
b = 10000
print(a is b) # 有时True 有时False
print(a == b) # True
a = -6
b = -6
print(a is b) # 有时True 有时False
print(a == b) # True
a = [1, 5]
b = [1, 5]
c = a
print(a is b) # False
print(a == b) # True
print(c is a) # True
print(c == a) # True
print(c is b) # False
print(c == b) # True

概念

在 Python 中,is== 都用于比较,是分别根据对象的内存地址和对象的值来判断,所以用途上也不一样。

用图书馆的书籍可以打个值和内存地址形象的比喻:

  • 对象的值,就像书籍内容:
    • 每本书都有它的内容,例如文字、图片等,这代表了书的“值”。
    • 不同的书可能有相同的内容(例如两本相同的书),但它们仍然是不同的实体。
  • 对象的内存地址,书籍在图书馆中的位置:
    • 每本书在图书馆中都有一个特定的位置,比如在某个书架的某一层某一排。
    • 即使两本书的内容完全相同,如果它们在不同的位置上,它们就是两个不同的对象。

is 身份运算符

is 用于比较两个对象的身份,即比较两个对象在内存中的地址(内存地址可以用Python内建函数id()查看,它会返回一个整数)是否相同。换句话说,它检查的是两个对象是否是同一个对象。

回到开头测试例子里:

# 注意:以下id函数计算出的内存地址整数不一定是代码的那些整数
a = 1
b = 1
print(id(a), id(b)) # 输出:2398302306544 2398302306544
print(a is b) # True,因为a和b的id内存地址相同,所以a和b是同一个对象

a = [1, 5]
b = [1, 5]
print(id(a), id(b)) # 输出:2398357892288 2398357883648
print(a is b)  # 输出: False,因为a和b的id内存地址不同,所以a和b是不同的对象,即使它们的值相同

c = a
print(id(a), id(c)) # 输出:2398357892288 2398357892288
print(a is c)  # 输出: True,因为c和a的id内存地址相同,所以c和a是同一个对象
== 比较运算符

== 用于比较两个对象的值是否相等。它检查的是对象的是否相同,而不是对象本身是否相同(虽然拗口,但事实如此)。 这意味着即使是两个不同的对象,只要它们的值相同,== 比较的结果就是 True。

a = 1
b = 1
print(a == b)  # 输出: True,因为 a 和 b 的值相同

a = [1, 5]
b = [1, 5]
c = a
print(a == b)  # 输出: True,因为 a 和 b 的值相同
print(c == b)  # 输出: True,因为 c 和 b 的值相同

通常情况下,== 可以通过重载 __eq__ 方法来定义值比较行为, 再举回书籍的例子,我们用书籍内容content来表示对象的值,location不是内存地址

class Book:
    def __init__(self, location, content):
        self.location = location
        self.content = content

    def __eq__(self, other):
        if isinstance(other, Book):
            return self.content == other.content
        return False

    def __repr__(self):
        return f"Book(content='{self.content}')"

# 创建两个 Book 对象
book1 = Book(location="A", content="Hello")
book2 = Book(location="B", content="Hello")
book3 = Book(location="C", content="Hi")

# 比较对象
print(book1 == book2)  # 输出: True,因为 content 相同
print(book1 == book3)  # 输出: False,因为 content 不同

# 查看对象内存地址,不同的对象
print(id(book1)) # 输出: 1907430631760
print(id(book2)) # 输出: 1907430632240
print(id(book3)) # 输出: 1907430632336

注意

共用缓存对象

你也许发现了is在某些情况下判断并不稳定,比如测试例子中ab都等于10000(或-6)时,a is b有时候会等于False,有时候会等于True

这主要是因为Python对于一些小整数(通常在-5256之间,范围并不是固定)和一些字符串进行了缓存,所以这些对象在内存中会被重用。 当比较这些小整数和字符串时,is 比较时可能返回 True,即使你认为它们是不同的对象。

所以涉及到这些对象进行比较时,一般不用is而是==

单例模式

在单例模式下,所有构造出来的对象实际上都是同一个实例,因此使用 is== 进行比较时,结果都应该是 True,但一般都是用is来判断。

这是因为使用 is 来判断更加直观和高效, is比较的是对象的身份(即内存地址),而 == 比较的是对象的值,要先找到地址才能找到值,而且某些值比较时需要进行额外计算消耗资源(参考找书籍的例子)。

在python中有些比较特殊的对象如NoneTrueFalse等,它们都是个单例对象,所以通常判断一个变量是否为这些对象时应该使用 is 而不是 ==

应用场景

  • is主要用于判定是不是同一个对象,在与单例对象比较时,一般都是有is来判断
  • ==通常是用于两个对象确切的值的比较,比如字符串比较,数值比较。

总结

  • ==:比较两个对象的值是否相等。
  • is:比较两个对象的身份(内存地址)是否相同。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容