首先,不用解释器,脑补一下下面这段代码的结果是什么
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