首先,不用解釋器,腦補一下下面這段代碼的結果是什麼
1 2 3 4 5 6 7 8 |
def add(lst1,lst2): for i in xrange(len(lst1)): lst1[i]+=lst2[i] a=[[0]*3]*3 add(a[0],[1,0,0]) add(a[1],[0,1,0]) print a[1] |
有沒有娃兒和我一樣覺得是[0,1,0]的?
實際上結果出人意料地是[1,1,0]
WTF!昨天晚上我想了三宿都沒明白Σ(`д′*ノ)ノ 後來吃了一個橙子終於想通了
a=[[0]*3]*3這句話來將a賦值成 [[0,0,0],[0,0,0],[0,0,0]],然而python似乎是這樣賦值的:
為了驗證這個猜想我們用內置函數id來打印內存地址(僅對cpython而言)
1 2 3 4 5 6 |
>>> id(a[0]) 38025256 >>> id(a[1]) 38025256 >>> id(a[2]) 38025256 |
這證明了我們的猜想。
那麼如果我用下面這句話來初始化a呢?
1 |
a=[[0]*3 for i in range(3)] |
這次直接看id:
1 2 3 4 5 6 |
>>> id(a[0]) 38056704 >>> id(a[1]) 38056744 >>> id(a[2]) 33504712 |
不一樣了吧。可見使用列表推導式時,每次都會重新計算一次[0,0,0]的值(在這個例子中它不隨i變化),而不會去引用之前的結果;或者說,*運算符作用於列表時產生n個對原對象的引用,而不是真正的複製
還有個有趣的現象
1 2 3 4 5 |
>>> a=1 >>> id(a) 38176416 >>> id(1) 38176416 |
真特么摳門,真不知道cpython的內存回收是怎麼做的,有空去看看源碼(* ̄︶ ̄)y
有意思~
請問吃的是什麼橙子?
淘寶上買的
少年,我就喜歡你裝逼的樣,昨晚想了三宿,吃了一個橙子
去你Y的
hiahia mutable object的話都會碰到這個問題的,因為默認是引用傳值,如果是int,string這種immutable的就不會出現這個問題了
好的你成功地吸引了我的注意快告訴我你是誰[思考]
昨天在群里發言的那位[福到啦]
最近正好想整理一下各種編程語言下一些tiny but vital的區別,大概想整理成這個樣子:
咦,這裡不能上傳圖片。。。
你可以用第三方圖床【多說渣渣
難道是qq群www我潛水一萬年了www並不知道是哪個群
類似列表這些mutable對象用deep copy複製一下就不會複製為引用了~~~話說我還在想為啥取個快屌這麼猥瑣的名字……知道我發現了評論框的菊花……
嗯,我是不是應該改成一根黃瓜2333