以前老是不注意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. 【Loadrunner】通过loadrunner录制时候有事件但是白页无法出来登录页怎么办?

    loadrunner录制脚本时候有事件但是一直白页怎么办? 解决办法:依次进行下方1.2.方法操作,如果还不行再进行3的操作. 1.勾选下图IE浏览器的Internet选项中“启用第三方浏览器拓展*” ...

  2. 006-ant design -结合echart-地址map市

    基于上节的引用 // 引入 ECharts 主模块 import echarts from 'echarts/lib/echarts'; // 引入 ECharts 图形模块 import 'echa ...

  3. 百度天气接口api

    百度天气接口 以GET形式提交,返回JSON或XML URL:http://api.map.baidu.com/telematics/v3/weather?location={城市名}&out ...

  4. python第三方模块之paramiko模块

    目录: paramiko模块介绍 paramiko模块安装 paramiko模块使用 一.paramiko模块介绍 paramiko是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件 ...

  5. hadoop中map和reduce的数量设置

    hadoop中map和reduce的数量设置,有以下几种方式来设置 一.mapred-default.xml 这个文件包含主要的你的站点定制的Hadoop.尽管文件名以mapred开头,通过它可以控制 ...

  6. Kafka丢失数据问题优化总结

    数据丢失是一件非常严重的事情事,针对数据丢失的问题我们需要有明确的思路来确定问题所在,针对这段时间的总结,我个人面对kafka 数据丢失问题的解决思路如下: 是否真正的存在数据丢失问题,比如有很多时候 ...

  7. hdu 5140 主席树

    这题说的是每个员工有工资 水平 在公司待的年限这几个属性,有大量的查询 查的是在一定的水平和工作年限的工人总工资是多少 这个思路是比较简单的我们按照他们的水平排序,排完后,使用主席树不断地往里面插,然 ...

  8. bootstrap详解 见网址

    http://caibaojian.com/bootstrap/base-css.html?#forms

  9. Python 非递归遍历图

    class Queue: def __init__(self,max_size): self.max_size = int(max_size) self.queue = [] def put(self ...

  10. pug 在线文档

    https://pugjs.org/zh-cn/api/getting-started.html