【Python基础】“==” 操作符与 “is” 操作符的区别

等于(==)操作符和 is 操作符 是 Python 中对象比较常用的两种方式。简单来说:

  • “==” 操作符比较的是两个对象之间的值是否相等
  • 而 “is” 操作符比较的是对象的身份标识是否相等。在 Python 中,每个对象的身份标识,都能通过函数 id(object) 获得。因此,'is’操作符,相当于比较对象之间的 ID 是否相等,即它们是否为同一对象,是否指向同一个内存地址

注意点 1

a = 10
b = 10

a == b
True

id(a)
4427562448

id(b)
4427562448

a is b
True

这里,首先 Python 会为 10 这个值开辟一块内存,然后变量 a 和 b 同时指向这块内存区域,即 a 和 b 都是指向 10 这个变量,因此 a 和 b 的值相等,id 也相等,a == b和a is b都返回 True。

对于整型数字来说,以上 a is b 返回为 True 的结论,只适用于 -5 到 256 范围内的数字。这是因为,出于对性能优化的考虑,在 CPython(Python 的 C 实现)的实现中,会对 -5 到 256 的整数维持一个数组,起到一个缓存的作用。这样,每次你试图创建一个 -5 到 256 范围内的整型数字时,Python 都会从这个数组中返回相对应的数字对象的引用,而不是重新开辟一块新的内存空间。也就是说,这个区间里的数字都会引用同一块内存区域。

a = 257
b = 257

a == b
True

id(a)
4473417552

id(b)
4473417584

a is b
False

但是,如果整型数字超过了这个范围,会因为你的重新定义而被重新分配内存。比如 257,可以看到 a == b 仍然返回 True,但 a is b 返回了 False,并且 a 和 b 的 ID 不一样了。这是因为,Python 会为两个 257 分别开辟两块内存区域,a 和 b 指向的是不同的内存地址。

注意点 2

比较操作符’is’的速度效率,通常要优于’==’。

因为’is’操作符不能被重载,这样,Python 就不需要去寻找,程序中是否有其他地方重载了比较操作符,并去调用。执行比较操作符’is’,就仅仅是比较两个变量的 ID 而已。

但是 ‘==’ 操作符却不同,会递归地遍历对象的所有值,并逐一比较。执行a == b相当于是去执行a.__eq__(b),而 Python 大部分的数据类型都会去重载__eq__这个函数,其内部的处理通常会复杂一些。比如,对于列表,__eq__函数会去遍历列表中的元素,比较它们的顺序和值是否相等。

注意点 3

对于不可变(immutable)的变量,如果我们之前用 ‘==’ 或者 ‘is’ 操作符比较过,结果不一定就是一成不变的。因此,在必要的地方不要省略条件检查

举个例子,元组是不可变的,但元组可以嵌套,它里面的元素可以是列表类型,列表是可变的,所以如果我们修改了元组中的某个可变元素,那么元组本身也就改变了,之前用’is’或者’=='操作符取得的结果,可能就不适用了。

t1 = (1, 2, [3, 4])
t2 = (1, 2, [3, 4])
t1 == t2
True

t1[-1].append(5)
t1 == t2
False

注意点 4

当和 None 进行比较时,永远使用操作符 ‘is’。当你明确想要比较对象是否是 None 时,一定要显式地用 is None。

(1)对于类来说,== 的结果,取决于它的__eq__()方法的具体实现。因此,有的时候,采用 “==” 操作符的结果不一定如你所愿。

class MyObject(object):
 def __eq__(self, other):
   if other:
     return self.field == other.field
   return True


# 错误示例
x = MyObject()
print(x == None) 


# 正确示例
x = MyObject()
print(x is None)

(2)避免 Python 中的隐式布尔转换带来的问题

# 错误示例
def pay(name, salary=None):
 if not salary:
   salary = 11
 print(name, "is compensated", salary, "dollars")

上面这段代码,如果有人调用 pay(“Andrew”, 0) ,会打印成 “Andrew is compensated 11 dollars”。

# 正确示例
def pay(name, salary=None):
 if salary is not None:
   salary = 11
 print(name, "is compensated", salary, "dollars")

参考

《Python核心技术与实战》

git+pylint实现python提交代码格式校验

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值