美文网首页python热爱者Python新世界
百分之九十的人都答不对这道Python题,这个真的不是标题党!

百分之九十的人都答不对这道Python题,这个真的不是标题党!

作者: 48e0a32026ae | 来源:发表于2018-11-04 16:40 被阅读0次

每种编程语言都有一些不为人知的陷阱,有些实际工作中会踩到,有些可能根本排不上用场,但弄明白这些陷阱有利于我们更好的去了解这门语言的实现机制。

下面这个题,你是否能一眼看出问题的本质。

学习Python中有不明白推荐加入交流群

                号:516107834

                群里有志同道合的小伙伴,互帮互助,

                群里有不错的学习教程!

# 第一组

>>> a = 256

>>> b = 256

>>> a is b

True

# 第二组

>>> a = 257

>>> b = 257

>>> a is b

False

# 第三组

>>> a = 257; b = 257

>>> a is b

True

不管是 Python2 还是 Python3 环境下,只要你是在 CPython 的交互式命令行 REPL 中执行,结果没什么不同。

我们知道 is 比较的是两个对象的内存地址是否一样( id 函数返回一个和对象的内存地址相关的值),言外之意就是看a,b两个变量是否指向同一个对象。我们来看看每个变量的 id 值。

>>> a = 256

>>> id(a)

1721788128

>>> b = 256

>>> id(a)

1721788128

>>> a = 257

>>> id(a)

14947024

>>> b = 257

>>> id(b)

14947104

>>> a = 257; b=257

>>> id(a)

14947136

>>> id(b)

14947136

>>>

不出所料,前后两组 a,b的 id 值是相同的,只有中间这组 id 值不一样,我们可以对其简单分析一下原因。在 Python 中,一切皆为对象,理论上任意两个对象的 id 值都是不一样的,例如:

>>> nums = [1,2,3,4]

>>> id(nums)

15148936

>>> nums2 = [1,2,3]

>>> id(nums2)

15160824

>>> nums3 = [1,2,3]

>>> id(nums3)

15160864

看得出每个对象的 id 值是不同的,哪怕两个对象的值(内容)相同,他们的 id 值也是不一样的(nums2和nums3)。那为什么前面第一组两个对象的id值相同呢?可能有些同学已经知道了

因为在 Python 中,我们需要使用对象的时候 Python 就会为我们创建好,当不需要了它就会进行回收,就好比屋子里面的东西用完之后,要及时清理,否则整个屋子很快就会堆满,最终导致房间再也塞不进任何东西。

同样的,为了提高性能,Python 就把一些常用的整数专门缓存起来,就像屋子里面有些东西总是每天都要频繁使用,比如床,你不能说睡完之后,就把床搬出去,要用了再搬回来,这样的效率太低,因为这个搬运过程实在是太耗时了。于是,我们可以专门拿一块空间用来放置这个床。

Python 中也是同样的道理,因为整数是我们经常使用的对象,为了避免重复的创建、回收,干脆就把那些常用的整数缓存起来,每次需要使用时直接从缓存中拿,而不是重新创建(重新创建的话,肯定是一个全新的对象)。这些整数的范围是[-5, 256],当然这个数字范围是Python之父决定的,你要改,必须重新编译Python环境。

现在我们就能解释第一组为什么是True,第二组为什么是False了。为什么第三组结果又是 True 了?,不是说好大于256的整数不再缓存,每次使用都是新对象吗?别急,再听我啰嗦一下。

还是出于性能考虑,Python内部做了进一步优化,怎么优化呢?但凡是在同一个代码块中的代码,如果出现两个值相同的整数,那么它们将被重用,来看下面这个代码:

# test.py

# -*- coding: utf-8 -*-

a = 257

b = 257

def func():

c = 257

print(a is c) # False

print(a is b) # True

func()

上面代码是在一个 test.py 文件中,运行时,a和b的id值相同,而c的id值与a不一样,因为a、b 在同一个代码块,属于模块级别,而 c 是在函数里面,属于局部变量,他们不属于同一代码块中,因此函数里面的 257 这个对象时会重新创建,而创建 b 的时候,发现同级代码块中有个257的值了,就重用了这个对象。

再回到前面讲的第三组值,在 Python 的交互式命令行 REPL 中,每单独一行都视为一个代码块,同一行中的代码属于同一个代码块,因此不难理解,第三组中的a和b处在同一个代码块中,所以后者重用了前者,因此,两个变量的id是相同的。

有没有觉得这是一个坑。虽然我们实际场景中并不一定能用上,但是至少我们知道了Python为我们做的一些优化工作。

相关文章

网友评论

    本文标题:百分之九十的人都答不对这道Python题,这个真的不是标题党!

    本文链接:https://www.haomeiwen.com/subject/jntdxqtx.html