听说92.8%的人答不对这道Python题,我不信,后来我信了!真有趣
每種編程語言都有一些不為人知的陷阱,有些實際工作中會踩到,有些可能根本排不上用場,但弄明白這些陷阱有利于我們更好的去了解這門語言的實現機制。
下面這個題,你是否能一眼看出問題的本質。
不管是 Python2 還是 Python3 環境下,只要你是在 CPython 的交互式命令行 REPL 中執行,結果沒什么不同。
我們知道 is 比較的是兩個對象的內存地址是否一樣( id 函數返回一個和對象的內存地址相關的值),言外之意就是看a,b兩個變量是否指向同一個對象。我們來看看每個變量的 id 值。
不出所料,前后兩組 a,b的 id 值是相同的,只有中間這組 id 值不一樣,我們可以對其簡單分析一下原因。在 Python 中,一切皆為對象,理論上任意兩個對象的 id 值都是不一樣的!
例如:
嗨嘍:小編是一名python開發工程師,這里有我自己整理了一套最新的python系統學習教程, 包括從基礎的python腳本到web開發、爬蟲、數據分析、數據可視化、機器學習等。想要的加Q裙:895817687>>> 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內部做了進一步優化,怎么優化呢?但凡是在同一個代碼塊中的代碼,如果出現兩個值相同的整數,那么它們將被重用,來看下面這個代碼:
嗨嘍:小編是一名python開發工程師,這里有我自己整理了一套最新的python系統學習教程, 包括從基礎的python腳本到web開發、爬蟲、數據分析、數據可視化、機器學習等。想要的加Q裙:895817687# test.py # -*- coding: utf-8 -*- a = 257 b = 257 def func():c = 257print(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為我們做的一些優化工作。
總結
以上是生活随笔為你收集整理的听说92.8%的人答不对这道Python题,我不信,后来我信了!真有趣的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 123456789怎样运算等于1?答案可
- 下一篇: Python中from import和i