以前老是不注意python对象引用,平时也没遇到这样的问题,昨天在这个小问题纠结了半天时间。真是TMD啊

先说明一下我的目的,我有一个包含16个元素的列表,每个元素也是一个小列表。我想每四个子列表为一个单位,改变每个子列表的第一个元素为我想要的值。

代码如下

>>>a = range(1,5)

>>>b = [[0]*3]*16

>>>for i in range(4):
    each = b[i*4:(i+1)*4]
    for item in each:
        item[0]=a[i]
        print it

[1, 0, 0]
[1, 0, 0]
[1, 0, 0]
[1, 0, 0]
[2, 0, 0]
[2, 0, 0]
[2, 0, 0]
[2, 0, 0]
[3, 0, 0]
[3, 0, 0]
[3, 0, 0]
[3, 0, 0]
[4, 0, 0]
[4, 0, 0]
[4, 0, 0]
[4, 0, 0]

嗯,是我想看到的结果,可是我想要的不是打印出来,可是我把b打印出来,我去,怎么成下面这个鸟样

[[4, 0, 0], [4, 0, 0], [4, 0, 0], [4, 0, 0], [4, 0, 0], [4, 0, 0], [4, 0, 0], [4, 0, 0], [4, 0, 0], [4, 0, 0], [4, 0, 0], [4, 0, 0], [4, 0, 0], [4, 0, 0], [4, 0, 0], [4, 0, 0]]

于是我分析了几遍那两个for循环,都开始怀疑电脑是不是坏了。。。最后也没分析出个结果,于是我上开源中国那求助了,结果是我自己构造列表时就错了。

b = [[0]*3]*16这种方法构造的列表,十六个元素都是列表中第0个元素的引用,并没有真的开辟新的空间:b[0] is b[1] 会返回True,is好似通过对象的id来判断是否同一个对象,也就是说b[0]和b[1]的id是相同的。

那么这种构造列表方法就真的达不到我的目的了?no,no,no!python复制里有浅复制和深复制。这种构造方法就是列表中后面的元素浅复制了第一个元素。我们只要在后面的for循环里引入深复制,即可达到目的。

>>>b1= []
>>> for i in range(4):
    each = copy.deepcopy(b[i*4:(i+1)*4])
    for item in each:
        item[0]=a[i]
        b1.append(item)

>>> b1
>>>[[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0], [2, 0, 0], [2, 0, 0], [2, 0, 0], [2, 0, 0], [3, 0, 0], [3, 0, 0], [3, 0, 0], [3, 0, 0], [4, 0, 0], [4, 0, 0], [4, 0, 0], [4, 0, 0]]

不过这种方法归根接底并没有解决上面的构造列表时对象引用时钱复制的问题,因为这样以后b列表还是所有元素都和第0 个元素一样。

下面我们换种构造列表的方法,递推式构造列表。

>>> b = [[0]*3 for i in range(16)]
>>> b
>>>[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]

虽然看起来和上一种方法一个鸟样,但这只是表象。

用b[0] is b[1] 验证一下,果然返回的是False。说明这种构造方法会给推导式中每个元素都开辟新的空间,也就是说b[0]和b[1]的id是不同的。

for i in range(4):
    each = b[i*4:(i+1)*4]
    for item in each:
        item[0]=a[i]

>>> b
>>>[[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0], [2, 0, 0], [2, 0, 0], [2, 0, 0], [2, 0, 0], [3, 0, 0], [3, 0, 0], [3, 0, 0], [3, 0, 0], [4, 0, 0], [4, 0, 0], [4, 0, 0], [4, 0, 0]]

用这种方法构造的时,没有调用deepcopy这个方法,就可以达到效果。。。

总结一下:构造列表时注意,使用乘号构造是钱复制,所有对象都引用第0个元素,使用列表推导时直接开辟新空间,不存在复制不复制。

想了解python的复制及对象引用可以参考http://www.cnblogs.com/BeginMan/p/3197649.html

python 列表构造时的引用问题的更多相关文章

  1. Python 列表切片陷阱:引用、复制与深复制

    Python 列表的切片和赋值操作很基础,之前也遇到过一些坑,以为自己很懂了.但今天刷 Codewars 时发现了一个更大的坑,故在此记录. Python 列表赋值:复制"值"还是 ...

  2. python 列表和字典的引用与复制(copy)

    列表或字典的引用: 引用针对变量的时候,传递引用后,对引用后的对象的值进行改变是不会影响到原值的:而列表不一样如: spam =42 cheese = spam spam =100 print(spa ...

  3. Python列表,元组,字典,序列,引用

    1.列表 # Filename: using_list.py # This is my shopping list shoplist=["apple", "mango&q ...

  4. python列表与集合,以及循环时的注意事项

    一.python列表 序列是Python中最基本的数据结构.序列中的每个元素都分配一个数字 - 它的位置,或索引,第一个索引是0,第二个索引是1,往后数的最后一个为-1依此类推. Python有6个序 ...

  5. 使用gc、objgraph干掉python内存泄露与循环引用!

    Python使用引用计数和垃圾回收来做内存管理,前面也写过一遍文章<Python内存优化>,介绍了在python中,如何profile内存使用情况,并做出相应的优化.本文介绍两个更致命的问 ...

  6. python列表类型

    列表类型简介 列表类型是一个容器,它里面可以存放任意数量.任意类型的数据. 例如下面的几个列表中,有存储数值的.字符串的.内嵌列表的.不仅如此,还可以存储其他任意类型. >>> L ...

  7. Python列表、元组、字典和字符串的常用函数

    Python列表.元组.字典和字符串的常用函数 一.列表方法 1.ls.extend(object) 向列表ls中插入object中的每个元素,object可以是字符串,元组和列表(字符串“abc”中 ...

  8. python 列表与元组的操作简介

    上一篇:Python 序列通用操作介绍 列表 列表是可变的(mutable)--可以改变列表的内容,这不同于字符串和元组,字符串和元组都是不可变的.接下来讨论一下列表所提供的方法. list函数 可以 ...

  9. python 深入理解 赋值、引用、拷贝、作用域

    在 python 中赋值语句总是建立对象的引用值,而不是复制对象.因此,python 变量更像是指针,而不是数据存储区域, 这点和大多数 OO 语言类似吧,比如 C++.java 等 ~ 1.先来看个 ...

随机推荐

  1. 详解maxlength属性在textarea里奇怪的表现

    这篇文章主要介绍了maxlength属性在textarea里奇怪的表现的相关资料,需要的朋友可以参考下 HTML5给表单带来了很多改变,比如今天要说的maxlength,这个属性可以限制输入框输入的最 ...

  2. Openstack(十七)部署快存储cinder

    官方部署文档:https://docs.openstack.org/ocata/zh_CN/install-guide-rdo/cinder.html OpenStack的存储组件—Cinder和Sw ...

  3. cocos代码研究(22)Widget子类Layout学习笔记

    理论基础 一个包含控件的容器. 子节点可以根据布局类型重新排序,它还可以开启剪裁,设置背景图像和颜色.继承自Widget,以及LayoutProtocol. 被 HBox, PageView, Rel ...

  4. uva1401 dp+Trie

    这题说的是给了一个长的字符串长度最大300000,又给了4000个单词 单词的长度不超过100.计算这个字符串能组成多少种不同单词的组合,求出方案总数.dp[i]以第i个字符为开始的字符串能有多少种的 ...

  5. 20155239 2016-2017-2 《Java程序设计》第7周学习总结

    教材学习内容总结 1.了解Lambda语言 "Lambda 表达式"(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的 ...

  6. 工具推荐. 在线unix, 在线python/perl脚本测试环境

    在线python, perl, javascript, Lisp, Ruby等  http://melpon.org/wandbox/ 正则表达式在线测试工具 http://tools.jb51.ne ...

  7. 文件名含中文的JavaWeb文件下载

    在javaweb项目中实现文件下载,当文件名中包含中文文字时,需要进行如下的处理,才能在浏览器端正常显示中文文件名: response.setContentType("octets/stre ...

  8. 独家揭秘,106岁的IBM靠什么完成了世纪大转型|钛度专访

    IBM大中华区董事长陈黎明 到2017年2月,陈黎明就担任IBM大中华区董事长整整两年了. 五年前,IBM历史上首位女CEO也是第9位CEO罗睿兰上任,三年前,IBM在罗睿兰的带领下以数据与分析.云. ...

  9. pyDay12

    内容来自廖雪峰的官方网站. 1.可迭代对象(Iterable):可以直接作用于for循环的对象. 2.集合数据类型:如list.tuple.dict.set.str等. 3.generator:包括生 ...

  10. 20145325张梓靖 《Java程序设计》第6周学习总结

    20145325张梓靖 <Java程序设计>第6周学习总结 教材学习内容总结 串流设计 输入串流(将数据从来源取出),代表对象为java.io.InputStream实例,输出串流(将数据 ...