python 的 is 与 == 区别

输入如下代码
>>> b = [0, 1]
>>> c = b[:]
>>> d = b
>>> print(b is c)
False
>>> print(b is d)
True

为什么会有如上结果呢?

"is" 比较的是两个实例对象是不是完全相同,它们是不是同一个对象,占用的内存地址是否相同。莱布尼茨说过:“世界上没有两片完全相同的叶子”,这个is正是这样的比较,比较是不是同一片叶子(即比较的id是否相同,这id类似于人的身份证标识)。

"==" 比较的是两个对象的内容是否相等,即内存地址可以不一样,内容一样就可以了。这里比较的并非是同一片叶子,可能叶子的种类或者脉络相同就可以了。默认会调用对象的 __eq__()方法。


可以通过 id 来查询分辨两个实例对象是否相同

>>> id(b)
2479316523720
>>> id(c)
2479316523912
>>> id(d)
2479316523720

这个其实就跟深浅层copy的原理很类似了。

  • 整形数据

在python IDE中,-5~256 范围的整形数,内存地址是缓存好的。如果超出这个范围,多次引用内存地址会发生变化。

>>> id(-6)
2479315586096
>>> id(-6)
2479315584432
>>> id(-5)
1524002080
>>> id(-5)
1524002080
  • 字符串

字符串算是进程里实例数量较多的类型之一,因为无处不在的名字就是字符串实例。

鉴于相同名字会重复出现在各种名字空间里,那么有必要让它们共享对象。内容相同,且不可变,共享不会导致任何问题。关键是可节约内存,且省去创建新实例的调用开销。

对此,Python 的做法是实现一个字符串池(intern)。池负责管理实例,使用者只需引用即可。另一潜在好处是,从池返回的字符串,只需比较指针就可知道内容是否相同,无需额外计算。可用来提升哈希表等类似结构的查找性能。

>> > "__name__" is sys . intern ( "__name__" )

True

除了以常量方式出现的名字和字面量外,动态生成字符串一样可加入池中。如此可保证每 次都引用同一对象,不会有额外的创建和分配操作。

>> > a = "hello, world!"

>> > b = "hello, world!"

>> > a is b   # 不同实例。

False

>> > sys . intern ( a ) is sys . intern ( "hello, world!" ) # 相同实例。

True

当然,一旦失去所有外部引用,池内字符串对象会被回收。

>> > a = sys . intern ( "hello, world!" )

>> > id ( a )

4401879024

>> > id ( sys . intern ( "hello, world!" ) ) # 有外部引用。

4401879024

>> > del a   # 删除外部引用后被回收。

>> > id ( sys . intern ( "hello, world!" ) ) # 从 id 值不同可以看到新建,入池。

4405219056

字符串池实现算法很简单,就是简单的字典结构。 详情参考 Objects/unicodeobject.c : PyUnicode_InternInPlace。

做大数据处理时,可能需创建海量主键,使用 intern 有助于减少对象数量,节约大量内存。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值