zoukankan      html  css  js  c++  java
  • list[] 和 list[:] 的区别

    list[] 和 list[:] 的理解

      list“赋值”时会用到list2 = list1 或者 list2[:] = list1,前者两个名字指向同一个对象,后者两个名字指向不同对象。理解如下:

     

      首先,python中没有赋值的说法,只有名称到对象的引用;

      list2 = list1是把list1所指的对象绑定到名字list2上,没有产生新list,只是新增了一个引用;

      正因为两个名称指向的同一个对象,所以修改list1,那么list2也会改变;

      通俗理解:以前有一套三室一厅的房子,户主叫list1。后来list1和list2结婚,房产证上户主的名字加了一个,但房子还是只有一套。list1如果把客厅刷成了蓝色,那list2回家的时候会发现客厅是蓝色的了。

     

      而list2 = list1[:]则是把list1通过切片运算取得的新list对象绑定到list2上,产生了新list,名称和引用也不同,所以,修改其中一个,另一个不会变。

      注意,这里的切片是浅拷贝,参考下面的笔记。

      通俗理解:从前有一套三室一厅的房子,户主叫list1。后来有个叫list2的,觉得list1的房子不错,于是买了一套相同户型的,也装修得一模一样。后来list1把自己的客厅刷成了蓝色,list2回家发现自己家的客厅还是白色,并没有变成蓝色。

     

    浅拷贝(shallow copy)

      浅拷贝会创建新对象,其内容是原对象的引用。

      浅拷贝有三种形式:切片操作,工厂函数,copy模块中的copy函数。

      比如对:a = [1,2,3,"hello",["python","C++"]]

        1、切片操作:b = a[:] 或者 b = [each for each in a]

        2、工厂函数:b = list(a)

        3、copy函数:b = copy.copy(a)

      浅拷贝产生的b不再是a了,使用is可以发现他们不是同一个对象,使用id查看,发现它们也不指向同一片内存。但是当我们使用 id(x) for x in a 和 id(x) for x in b 时,可以看到二者包含的元素的地址是相同的。

      在这种情况下,a和b是不同的对象,修改b理论上不会影响a。

      比如b.append([4,5]):

      b = a[:]

      b.append("ADD")

      输出:a [1, 2, 3, 'hello', ['python', 'C++']] b [1, 2, 3, 'hello', ['python', 'C++'], 'ADD']

      注:浅拷贝之所以称为浅拷贝,是它仅仅只拷贝了一层,在a中有一个嵌套的list,如果我们修改了它,情况就不一样了。

       a[4].append("C")。查看b,可发现b也发生了变化。这是因为,我们修改了嵌套的list。修改外层元素,会修改它的引用,让它们指向别的位置,修改嵌套列表中的元素,列表的地址并为发生变化,指向的都是同一个位置。

     

    深拷贝(deep copy)

      深拷贝只有一种形式,copy模块中的deepcopy函数。

      和浅拷贝对应,深拷贝拷贝了对象的所有元素,包括多层嵌套的元素。因而,它的时间和空间开销要高。

      同样对上述list类型的a,若使用b = copy.deepcopy(a),再修改b将不会影响到a了。即使嵌套的列表具有更深的层次,也不会产生任何影响,因为深拷贝出来的对象根本就是一个全新的对象,不再与原来的对象有任何关联。

  • 相关阅读:
    Android开发学习之路--Content Provider之初体验
    [NOI2005] 维修数列
    递归算法对完全二叉树的前序遍历
    非递归算法对完全二叉树的前序遍历
    java中的多态
    poj1088滑雪
    在网页中插入flash
    如何采用批处理文件安装一个.dll文件,并且注册
    结构体指针和数组理解
    完全二叉树
  • 原文地址:https://www.cnblogs.com/panweiwei/p/12748504.html
Copyright © 2011-2022 走看看