这一篇很重要,因为很多人刚学 Python 时,都会把 is 和 == 混着用。表面上它们有时候结果一样,但本质上判断的根本不是一回事。
学到这里,你已经接触过不少比较写法了。
比如:
print(10 == 10)print(name == '小明')print(score >= 60)
这些都不难理解。 其中 == 的意思也很明确,就是判断两个值是否相等。
可过一段时间,你又会遇到另一个看起来有点像的东西:
is
比如:
a is b
这时候很多新手会开始迷糊。
is 不也是在比较吗 那它和 == 到底差在哪 为什么有时候结果一样 为什么有时候别人又说不能乱用
今天这篇文章,我们就把这个问题彻底讲清楚。
你可以先记住一句最核心的话:
== 比较的是值是否相等is 比较的是是不是同一个对象
只要你把这句话真正理解了,后面这个知识点就不难了。
一、先从 == 开始,它判断的是值是否一样
这个你其实已经很熟了。
比如:
print(10 == 10)
结果是:
True
因为两个值都是 10。
再比如:
print('Python' == 'Python')
结果也是:
True
因为两个字符串内容一样。
所以 == 很好理解,它问的是:
左边的值和右边的值,内容上是不是相等
这就像你拿两张写着同样内容的纸比一比。 只要写的内容一样,它就会觉得相等。
二、is 判断的不是内容,而是“是不是同一个东西”
这就是最关键的区别。
来看一个最简单的例子:
a = Noneb = Noneprint(a is b)
结果通常是:
True
这表示 a 和 b 指向的是同一个 None 对象。
再看另一个例子:
a = [1, 2, 3]b = [1, 2, 3]print(a == b)print(a is b)
结果通常是:
TrueFalse
这里就特别能说明问题。
为什么 a == b 是 True因为两个列表内容一样,都是 [1, 2, 3]
为什么 a is b 是 False因为它们虽然内容一样,但并不是同一个对象
也就是说:
== 看的是内容is 看的是身份
三、先用一个生活比喻把它想明白
假设你有两本完全一样的书。
书名一样 内容一样 页数一样 封面一样
从“内容是否一样”这个角度看,它们当然相等。 这就像 ==。
但从“是不是同一本书”这个角度看,它们不是同一本。 只是两本一模一样的复制品。 这就像 is。
所以:
== 更像是在问 内容一样吗
is 更像是在问 是不是同一个东西
这个比喻你最好牢牢记住。
四、为什么初学时容易把它们混淆
因为在某些简单例子里,它们结果可能看起来一样。
比如:
a = Noneb = Noneprint(a == b)print(a is b)
结果都可能是:
TrueTrue
再比如某些小整数、短字符串,也可能出现这种情况。
于是很多新手就会以为:
哦,原来 is 和 == 差不多嘛
其实不是。
只是恰好在这些例子里, “值相等”和“是同一个对象”同时成立了。
一旦换到更复杂的数据,比如列表、字典、自定义对象,差别就会一下子变得很明显。
五、先做一个最典型的对比实验
下面这段代码,你最好亲手敲一遍。
a = [1, 2, 3]b = [1, 2, 3]print(a == b)print(a is b)
你会发现:
a == b 是 Truea is b 是 False
原因我们刚才已经说过了:
内容一样 但不是同一个对象
然后你再试这个:
a = [1, 2, 3]b = aprint(a == b)print(a is b)
这次结果通常会变成:
TrueTrue
为什么。
因为这里的 b = a 不是新建一个一模一样的列表, 而是直接让 b 指向了 a 本身。
这时候它们不只是内容一样, 而且真的是同一个对象。
这个例子非常值得你反复体会。
六、== 适合拿来比较值
这是你以后最常见的用法。
比如比较数字:
score = 100print(score == 100)
比较字符串:
name = input('请输入姓名:')print(name == '小明')
比较是否及格:
print(score >= 60)
这些场景,关注点都在“值对不对”“内容一不一样”。 所以用 == 最自然。
简单说:
只要你在意的是内容、结果、值本身 就优先想到 ==
七、is 最常见的正确用法,是和 None 一起用
这个是 Python 里一个非常经典的场景。
比如:
value = Noneprint(value isNone)
结果通常是:
True
如果后来你给它赋了别的值:
value = 'hello'print(value isNone)
结果就会是:
False
为什么这里推荐用 is None,而不是 == None
因为 None 是一个非常特殊的单独对象。 你在判断一个变量是不是 None 时, 本质上就是在问:
它是不是那个特殊的 None 对象
所以写成:
value isNone
会更清楚,也更符合 Python 里的常见习惯。
八、为什么判断 None 时更推荐用 is
你现在先不用深究太底层的细节, 先记结论就行:
判断是不是 None,推荐写:
value isNone
判断不是 None,推荐写:
value isnotNone
比如:
name = Noneprint(name isNone)print(name isnotNone)
结果大概是:
TrueFalse
再比如:
name = '小明'print(name isNone)print(name isnotNone)
结果就会反过来:
FalseTrue
这个写法以后你会见得非常多。 尤其是后面学函数、处理空值、判断变量状态时。
九、is not 也要顺手记住
既然有 is,自然也有它的反面:
isnot
这个的意思很简单:
不是同一个对象
比如和 None 配合:
email = Noneprint(email isnotNone)
结果是:
False
如果后面有内容了:
email = 'test@example.com'print(email isnotNone)
结果就是:
True
你可以把它理解成:
有值了吗 不再是空状态了吗
这个写法在后面会非常常见。
十、什么时候用 ==,什么时候用 is
这个问题最实用,直接给你一个清楚的判断标准。
如果你要比较的是:
数字 字符串 列表内容 字典内容 分数 用户名 商品价格 各种具体值
优先用:
==
如果你要判断的是:
是不是 None是不是同一个对象 两个变量是不是引用同一个东西
优先用:
is
你现阶段最稳的策略其实很简单:
大多数“比较值”的场景,用 ==大多数“判断 None”的场景,用 is
这样基本不会出大错。
十一、自己动手做一个对比实验
下面这段代码,建议你亲手跑一遍。
a = [1, 2, 3]b = [1, 2, 3]c = aprint(a == b)print(a is b)print(a == c)print(a is c)
你要重点观察:
为什么 a == b 是真 为什么 a is b 却是假 为什么 a == c 和 a is c 都是真
把这个例子真正看懂, 你对 is 和 == 的区别就会清楚很多。
十二、再看字符串和数字时的情况
很多时候你会发现,某些简单值上,is 和 == 结果看起来像一样。
比如:
a = 10b = 10print(a == b)print(a is b)
或者:
a = 'hello'b = 'hello'print(a == b)print(a is b)
在某些环境下,它们都可能是 True。
但你千万不要因为这种现象,就得出一个结论说:
那以后用 is 也可以比较值嘛
不行。
因为这只是某些简单对象在实现层面上的表现。 它不是你应该依赖的比较规则。
你写代码时,最重要的是表达清楚你的意图。
如果你要比较值,就老老实实用 ==。 别因为偶尔看起来结果一样,就把 is 拿来乱替代。
十三、为什么说“别拿 is 乱比值”
因为 is 比的是对象身份, 不是值本身。
一旦你换一种数据结构,或者换一种构造方式, 结果就可能完全不一样。
比如我们刚才已经看过:
a = [1, 2, 3]b = [1, 2, 3]
内容一样,但 a is b 是 False。
所以你如果本来只是想比较内容, 却误用了 is, 程序就可能写出逻辑 bug。
这类 bug 有时候还挺隐蔽。 因为它在简单情况里能跑, 在复杂情况里却悄悄错掉。
这比直接报错更麻烦。
十四、现在就能建立的一个好习惯
这个习惯非常值得你从现在开始养。
比较值,一律优先想到:
==
判断是不是 None,一律优先想到:
isNoneisnotNone
只要你把这个习惯养稳, 以后大多数场景都不会混。
写代码最怕的不是不会, 而是会一点但规则没分清。 这个点就是典型例子。
十五、自己做一个 None 判断练习
下面这个练习很适合现在做。
result = Noneprint(result isNone)print(result == None)
你会发现很多时候它们结果看起来都一样。
然后你再改成:
result = '查询成功'print(result isNone)print(result == None)
结果会变成:
FalseFalse
这时候你就更容易理解:
虽然表面上有些时候 == None 也能工作, 但表达“是不是 None”这个意思时,is None 更准确、更清楚。
十六、实操,做一个用户信息是否已填写的小练习
phone = Noneemail = 'test@example.com'print(phone isNone)print(email isNone)print(phone isnotNone)print(email isnotNone)
运行后你会很直观地看到:
哪个还没填 哪个已经有值
这种判断以后特别常见。
比如:
头像是否上传 邮箱是否填写 备注是否为空 查询结果是否存在
这些都很适合用 is None / is not None 来表达。
十七、再做一个“同一个对象”实验
这个实验特别能帮助你理解 is 的本意。
list1 = [10, 20]list2 = [10, 20]list3 = list1print(list1 == list2)print(list1 is list2)print(list1 == list3)print(list1 is list3)
你重点体会这两组差异:
list1 和 list2内容一样,但不是同一个对象
list1 和 list3不只是内容一样,而且就是同一个对象
这就是 is 的真正意义。
十八、把今天这件事用一句人话彻底说清
以后你只要看到:
a == b
脑子里就翻译成:
a 和 b 的内容一样吗
看到:
a is b
脑子里就翻译成:
a 和 b 是不是同一个东西
如果你一直这样翻译, 这个知识点几乎就不会再乱。
很多编程概念一旦能翻译成人话, 就会一下子变得特别清楚。
十九、新手最容易犯的几个错误
第一个错误,拿 is 去比较普通值。
比如:
name is'小明'score is100
这种写法就算有时结果看着能对,也不推荐。 因为你真正想比较的是值,而不是对象身份。
第二个错误,把 == None 当成最推荐写法。
它有时能跑,但更推荐的是:
value isNone
第三个错误,看到某些简单例子里 is 和 == 结果一样,就以为它们可以随便互换。
不行。 它们本质判断的不是一件事。
第四个错误,不理解 b = a 和 b = [同样内容] 的区别。
这两个看起来很像, 但一个是指向同一个对象, 一个是新建一个内容一样的新对象。
二十、今天一定要亲手做的 3 个练习
第一个,值比较练习。
a = 100b = 100print(a == b)print(a is b)
第二个,列表对比练习。
a = [1, 2, 3]b = [1, 2, 3]c = aprint(a == b)print(a is b)print(a == c)print(a is c)
第三个,None 判断练习。
value = Noneprint(value isNone)print(value isnotNone)
这三个你只要亲手跑一遍,再自己改几个值试试, 这个知识点就会清楚很多。
二十一、再做一个综合小练习
下面这个小程序很适合拿来巩固今天的内容。
name = input('请输入姓名:')phone = Noneprint('------ 判断结果 ------')print(f'姓名是否是小明:{name == "小明"}')print(f'手机号是否为空:{phone isNone}')phone = '13800138000'print(f'手机号现在是否为空:{phone isNone}')print(f'手机号现在是否已有内容:{phone isnotNone}')
这个例子里你会同时看到:
值比较 None 判断 变量状态变化
特别适合你现在这个阶段去体会。
二十二、写在最后
is 和 == 这个知识点, 之所以总让新手犯迷糊, 不是因为它难,而是因为它们看起来太像了。
都像是在比较 都可能返回 True 或 False有时候简单例子里结果还刚好一样
但一旦你抓住最核心的区别, 这个问题其实非常清楚:
== 比值is 比身份
你现阶段最需要记住的,不是所有边边角角的细节, 而是先把两个最常用的原则养稳:
比较普通值,用 ==判断是不是 None,用 is
只要这两个原则不乱, 你后面写代码时就会稳很多。
本文小结
== 用来比较值是否相等。is 用来判断是不是同一个对象。 两个变量内容一样,不代表它们就是同一个对象。 比较数字、字符串、列表内容等普通值时,优先用 ==。 判断是否为 None 时,优先用 is None 或 is not None。 学习这个知识点的关键,不是死记定义,而是把它们分别翻译成“比值”和“比身份”。
下篇预告
第 20 篇,我们会对这一阶段做一个小总结。
基础类型小结:把最容易混淆的点一次讲透
到那一篇,我们会把数字、字符串、布尔值、None、类型转换、is 和 == 这些内容串起来,帮读者真正把基础数据类型这一块理顺。