Python, pitfall of creating 2d list, [foo*3]*3
2015-08-31 09:52
507 查看
When trying to create a 2d list, I used to write in this way since it looks simple and easy.
I didn’t realize its undesirable side effect until solving one problem yesterday.
The expected output should be
[ [10, 12, 12], [12, 12, 12], [12, 12, 12] ]
However, It actually becomes
[ [10, 12, 12], [10, 12, 12], [10, 12, 12] ]
output is
We notice that even if all elem in list have the same id, python will create a new object for a coming value because integer is immutable ( id(a[0]), id(a[1]) are different ).
output is
The picture for illustrating this problem is shown below
Although the list(id=4147958668) has been modified, all first elem in each list in 2D list are pointing to the first elem in list(id=4147958668). That is why all of them become 10.
Test
Output is
If we use this method, we find a[0], a[1], a[2] have different addresses. The picture is shown below
Test
Output is
It’s the same method as method 1
the third one is in my favorite one.
[code]a = [12*3]*3
I didn’t realize its undesirable side effect until solving one problem yesterday.
What is problem ?
if we are trying to change value of one element, the corresponding elem in each row will be modified.[code]a[0][0] = 10
The expected output should be
[ [10, 12, 12], [12, 12, 12], [12, 12, 12] ]
However, It actually becomes
[ [10, 12, 12], [10, 12, 12], [10, 12, 12] ]
The reason
1-D list
An experience is made to explain this problem. Here is a case for 1d list[code]a = [12]*5 print id(a) print id(a[0]), id(a[1]), id(a[4]) a[0] = 10 print a print id(a) print id(a[0]), id(a[1]), id(a[4])
output is
[code]4148536204 141234284 141234284 141234284 [10, 12, 12, 12, 12] 4148536204 141234308 141234284 141234284
We notice that even if all elem in list have the same id, python will create a new object for a coming value because integer is immutable ( id(a[0]), id(a[1]) are different ).
2-D list
[code]a = [[12]*3]*3 print id(a) print id(a[0]), id(a[0][0]), id(a[0][1]), id(a[0][2]) print id(a[1]), id(a[1][0]), id(a[1][1]), id(a[1][2]) print id(a[2]), id(a[2][0]), id(a[2][1]), id(a[2][2]) print a a[0][0] = 10 print a print id(a) print id(a[0]), id(a[0][0]), id(a[0][1]), id(a[0][2]) print id(a[1]), id(a[1][0]), id(a[1][1]), id(a[1][2]) print id(a[2]), id(a[2][0]), id(a[2][1]), id(a[2][2])
output is
[code]4147959532 4147958668 152936556 152936556 152936556 4147958668 152936556 152936556 152936556 4147958668 152936556 152936556 152936556 [[12, 12, 12], [12, 12, 12], [12, 12, 12]] [[10, 12, 12], [10, 12, 12], [10, 12, 12]] 4147959532 4147958668 152936580 152936556 152936556 4147958668 152936580 152936556 152936556 4147958668 152936580 152936556 152936556
The picture for illustrating this problem is shown below
Although the list(id=4147958668) has been modified, all first elem in each list in 2D list are pointing to the first elem in list(id=4147958668). That is why all of them become 10.
How to solve it ?
Method 1
[code]a = [x[:] for x in [[12]*3]*3]
Test
[code]a = [[12]*3]*3 print id(a) print id(a[0]), id(a[0][0]), id(a[0][1]), id(a[0][2]) print id(a[1]), id(a[1][0]), id(a[1][1]), id(a[1][2]) print id(a[2]), id(a[2][0]), id(a[2][1]), id(a[2][2]) print a a = [x[:] for x in [[12]*3]*3] print id(a) print id(a[0]), id(a[0][0]), id(a[0][1]), id(a[0][2]) print id(a[1]), id(a[1][0]), id(a[1][1]), id(a[1][2]) print id(a[2]), id(a[2][0]), id(a[2][1]), id(a[2][2])
Output is
[code]4148614892 4148614028 158683244 158683244 158683244 4148614028 158683244 158683244 158683244 4148614028 158683244 158683244 158683244 [[12, 12, 12], [12, 12, 12], [12, 12, 12]] 4148613388 4148615500 158683244 158683244 158683244 4148615276 158683244 158683244 158683244 4148615308 158683244 158683244 158683244
If we use this method, we find a[0], a[1], a[2] have different addresses. The picture is shown below
Mothod 2
[code]a = [[12 for x in range(3)] for y in range(3)]
Test
[code]a = [[12 for x in range(3)] for y in range(3)] print id(a) print id(a[0]), id(a[0][0]), id(a[0][1]), id(a[0][2]) print id(a[1]), id(a[1][0]), id(a[1][1]), id(a[1][2]) print id(a[2]), id(a[2][0]), id(a[2][1]), id(a[2][2])
Output is
[code]4148420908 4148422412 143655020 143655020 143655020 4148420876 143655020 143655020 143655020 4148423308 143655020 143655020 143655020
It’s the same method as method 1
Summary
The correct way to create 2D list arepython a = [x[:] for x in [[12]*3]*3] a = [[12 for x in range(3)] for y in range(3)] a = [ [12]*3 for dummy in range(3) ]
the third one is in my favorite one.
相关文章推荐
- windows和ubuntu下使用python写备份脚本
- Windows下安装python2.7及科学计算套装
- windows下python配置numpy、matplotlib、scipy
- Python 列表学习与使用
- 创建Python虚拟环境---Virtualenv
- Python2.7获取QQ空间全部好友
- Python源码剖析笔记6-函数机制
- 实例Python处理XML文件的方法
- Google提供的Python学习课程
- 【python】math模块的使用
- python 闭包(closure)
- 【python】判断年份是否为闰年
- map函数
- python中多进程的一般建议
- 2015/8/30 Python基础(4):序列操作符
- multiprocessing在python中的高级应用-托管对象
- python 小细节(01)
- Python爬虫学习记录(0)——Python 爬虫抓站 记录(虾米,百度,豆瓣,新浪微博)
- python关于爬虫编码备忘
- Python爬虫学习记录(4)——传说中的足彩倍投法。。好像也不是那么靠谱