不用共享引用创建一个列表的列表
来源:互联网 发布:找最大值 java 方法 编辑:程序博客网 时间:2024/05/29 14:30
Problem:
创建一个值全为0的三行五列的二维数组
Solution:
multilist = [[0 for col in range(5)] for row in range(3)]
Discussion:
为什么不能这样:
>>> multi = [[0] * 5] * 3
>>> multi
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
>>> multi[0][0] = 100
>>> multi
[[100, 0, 0, 0, 0], [100, 0, 0, 0, 0], [100, 0, 0, 0, 0]]
很奇怪吧?共享引用的问题。实际上上面的multi是通过下面两步来创建的:
>>> row = [0] * 5 # a list with five references to 0
>>> multi = [row] * 3 # a list with three references to the row object
通过把一个序列乘以n次创建的新序列中产生了n个新的引用,这些引用都指向原来的内容。如下:
>>> row.__str__
<method-wrapper '__str__' of list object at 0x823ebec>
>>> multi[0].__str__
<method-wrapper '__str__' of list object at 0x823ebec>
>>> multi[1].__str__
<method-wrapper '__str__' of list object at 0x823ebec>
>>> multi[2].__str__
<method-wrapper '__str__' of list object at 0x823ebec>
虽然row的创建也产生了五个指向整数0的引用,但被引用的对象是一个数,数是不可变的。也就是说如果一个对象是不可变的,对象本身和指向它的引用之间没有实质的区别。但在创建multi时产生了三个都指向列表row的引用,所以当你改变了multi中第一个列表中的每一个元素的值,也就改变了row的值,当然指向row的三个引用的值都改变了。
"Solution"中的列表解析能够避免上面的问题,列表解析是真正的嵌套计算,不会有共享引用发生。通过上面的讨论你可能会想,"Solution"中的内层列表解析实际上不是必需的,只要外层的列表解析就可以了。也就是说我们也可以这样写:
multilist = [[0]*5 for row in range(3)]
的确可以像上面那样写,实际上这种使用最内层列表乘法,其它外层列表解析的写法可以得到比上面另外两种写法快超过两倍的速度。但是与优化你的系统中较耗时的那部分代码相比,这里快的那二十几微秒根本不值一提。我们推荐"Solution"中用相同的方法构建内外列表的写法,可以使概念上更对称,更易读。
- 不用共享引用创建一个列表的列表
- 004_005 Python 在不适用引用的时候,创建列表的列表
- 创建一个虚列表控件
- 引用列表
- 一个列表的练习
- 创建一个带分组功能的下拉列表框控件
- 如何:创建一个所有者描述的列表框
- 创建一个目录列表进行每张sheet表的链接
- 创建了一个游戏相关的邮件列表欢迎加入
- 利用Expandable创建一个可以扩展的列表
- JS简单原生-定义一个创建HTML列表的方法
- drupal8里,怎么创建一个多条信息的列表
- 利用C#创建一个我们自己的列表
- 创建列表
- jquerymobile创建分割的列表
- 数据列表List的创建
- Android Dialog 列表的创建
- 列表视图控件的创建
- Test1说明
- 检查点9.1的三道题
- 打造酷炫风格的Swing界面
- Python小tips
- PKU 1061
- 不用共享引用创建一个列表的列表
- 面试技巧:16个经典面试问题回答思路
- 对象不同使用的区别
- sql2000行转列
- 韶慧,加油!
- 中国历史“四大谜案”
- 团队活动与团队士气
- 凹槽型光电开关WTK-10
- Javascript定义类或对象之动态原型法