• Python中对象的引用与复制


    在python进行像b = a这样的赋值时,只会创建一个对a的新引用,使a的引用计数加1,而不会创建新的对象:

    >>> a = 'xyz'
    >>> import sys
    >>> sys.getrefcount(a)
    3
    >>> b = a
    >>> sys.getrefcount(b)
    4
    >>> id(a)
    88292288L
    >>> id(b)
    88292288L
    

    这样,当引用的对象是可变对象的时候(列表,字典,可变集合等),会产生意料之外的行为:

    >>> a = [1, 2, 3, 4]
    >>> b = a
    >>> b.append(5)
    >>> a
    [1, 2, 3, 4, 5]
    

    因为a和b引用的是同一对象,改变其中一个,另外一个也会随之改变。当我们想建立一个副本而不是引用时,可以复制对象。

    复制对象一般使用copy模块:

    >>> a = [1, 2, 3, 4]
    >>> import copy
    >>> b = copy.copy(a)
    >>> b.append(5)
    >>> b
    [1, 2, 3, 4, 5]
    >>> a
    [1, 2, 3, 4]
    

    这样就可以了,但这种复制是一种浅复制,复制的新对象中包含的是对原始对象中的项的引用,如果对象的项为可变对象,也会产生不可控行为:

    >>> a = [1, [1, 2]]
    >>> b = copy.copy(a)
    >>> b[1].append(3)
    >>> b
    [1, [1, 2, 3]]
    >>> a
    [1, [1, 2, 3]]
    

    这时候就要使用深复制了。深复制将创建一个新对象,并递归地复制它所包含的所有对象:

    >>> a = [1, [1, 2]]
    >>> b = copy.deepcopy(a)
    >>> b[1].append(3)
    >>> b
    [1, [1, 2, 3]]
    >>> a
    [1, [1, 2]]
    

    对于不可改变的对象而言(字符串,数字,元组)等,没有必要拷贝,因为它们是不可改变的,不用担心会不经意间改动了它们。拷贝操作也只会得到原对象:

    >>> a = (1, 2, 3)
    >>> b = copy.copy(a)
    >>> a is b
    True
    

    对于可变对象来(列表,字典,可变集合)来说,可以分别使用内置函数list(),dict(),set()来进行浅复制,速度是比使用copy模块快的。

    列表也可以使用切片进行浅复制:

    >>> a = [1, 2, 3, 4]
    >>> b = a[:]
    >>> a is b
    False
    >>> b
    [1, 2, 3, 4]
    

    对序列数据类型(字符串,列表,元组)进行*操作时,也仅仅是复制了对象中项的引用,如果使用*创建一个多维列表:

    >>> a = [1, 2, 3]
    >>> b = [a]
    >>> c = b * 3
    >>> a.append(4)
    >>> c
    [[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]
    

    最好是在列表推导中使用浅复制来创建多维列表,可以避免隐式的引用共享:

    >>> a = [1, 2, 3]
    >>> c = [list(a) for i in range(3)]
    >>> a.append(4)
    >>> c
    [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
    

      

  • 相关阅读:
    学习进度八
    ”“口袋“app的nabcd
    学习进度7
    软工人3月7日学习记录
    软工人3月6日学习
    软工人3月5日学习
    开课博客
    android入门之Android环境配置
    大二寒假学习
    python链接数据库并创建表
  • 原文地址:https://www.cnblogs.com/linxiyue/p/7970287.html
Copyright © 2020-2023  润新知