zoukankan      html  css  js  c++  java
  • Python中的赋值和拷贝

    赋值

    在python中,赋值就是建立一个对象的引用,而不是将对象存储为另一个副本。比如:

    >>> a=[1,2,3]
    >>> b=a
    >>> c=a

    对象是[1,2,3]。分别由a、b、c三个变量其建立了相应的引用关系。而三个变量都不独占对象[1,2,3],或者说。能够通过不论什么一个变量来改动[1,2,3]这个对象。

    >>> c.append(4)
    >>> c
    [1, 2, 3, 4]
    >>> a
    [1, 2, 3, 4]
    >>> b
    [1, 2, 3, 4]
    >>> b.append("from b")
    >>> b
    [1, 2, 3, 4, 'from b']
    >>> a
    [1, 2, 3, 4, 'from b']
    >>> c
    [1, 2, 3, 4, 'from b']

    拷贝

    拷贝有浅拷贝和深拷贝之分。首先看以下的样例

    >>> a=[1,2,3]               #建立a与对象的引用连接
    >>> b=a                     #通过赋值。b也与对象建立引用
    >>> import copy
    >>> c=copy.copy(a)          #浅拷贝,建立了一个[1,2,3]的副本。即一个新的对象
    >>> d=copy.deepcopy(a)      #深拷贝,建立了一个[1,2,3]的副本。

    至此,a、b、c、d的关系例如以下图所看到的:

    a--|
         |-->[1,2,3]
    b--|

    c----->[1,2,3]

    d----->[1,2,3]

    改动a

    >>> a.append('aa')          #通过变量a改动原对象,使它变成[1,2,3,'aa']
    >>> b                       #b也同步改变
    [1, 2, 3, 'aa']
    >>> c                       #c相应的是一个副本。没有受到影响
    [1, 2, 3]
    >>> d                       #d同上道理
    [1, 2, 3]

    a、b、c、d的关系例如以下图所看到的:

    a--|
         |-->[1,2,3,'aa']
    b--|

    c----->[1,2,3]

    d----->[1,2,3]

    改动c:

    >>> c.append("cc")          #改动c的对象
    >>> a                       #a没有受到影响。由于a、c是指向不同对象
    [1, 2, 3, 'aa']
    >>> b
    [1, 2, 3, 'aa']
    >>> c
    [1, 2, 3, 'cc']
    >>> d
    [1, 2, 3]

    a、b、c、d的关系例如以下图所看到的:

    a--|
         |-->[1,2,3,'aa']
    b--|

    c----->[1,2,3,'cc']

    d----->[1,2,3]

    在上面的样例中,似乎copy和deepcopy没有什么差别,都是另外建立一个副本。且看例如以下样例:

    >>> q=[1,2,3,['a','b']]         #注意,这个对象是一个list,里面另一个元素是list,即q[3]=['a','b']
    >>> w=copy.copy(q)              #w、e分别是浅拷贝和深拷贝的副本对象引用
    >>> e=copy.deepcopy(q)
    
    >>> q.append('4q')              #q所相应的[1,2,3,['a','b']]变成[1,2,3,['a','b'],'4q']
    >>> q
    [1, 2, 3, ['a', 'b'], '4q']
    >>> w                           #w,e如同前面一样。没有受到影响
    [1, 2, 3, ['a', 'b']]
    >>> e
    [1, 2, 3, ['a', 'b']]

    改动w的相应列表

    >>> w.append(4)
    >>> w                           #添加了一个整数4
    [1, 2, 3, ['a', 'b'], 4]
    >>> q                           #q和e都没有受到影响
    [1, 2, 3, ['a', 'b']]
    >>> e
    [1, 2, 3, ['a', 'b']]
    >>> q
    [1, 2, 3, ['a', 'b']]

    改动w[3]的元素。提示:w是对q进行浅拷贝而得。

    >>> w[3].append('w3c')
    >>> q
    [1, 2, 3, ['a', 'b', 'w3c']]
    >>> w                               
    [1, 2, 3, ['a', 'b', 'w3c'], 4]
    >>> e
    [1, 2, 3, ['a', 'b']]

    细致观察上面的结果,发现:
    • q和w。当改动了列表里面的列表元素之后,两个同步改动了。

    • e没有受到影响

    也就是浅拷贝。仅仅建立了外层的副本,对于内层的副本没有建立;而深拷贝。建立了完整的副本。这就理解了汉语的翻译名称“浅”拷贝之含义了,其“浅”就是拷贝了一层(外层)。

    进一步改动e看看效果:

    >>> e.append('5e')
    >>> q
    [1, 2, 3, ['a', 'b', 'w3c']]
    >>> w
    [1, 2, 3, ['a', 'b', 'w3c'], 4]
    >>> e
    [1, 2, 3, ['a', 'b'], '5e']
    >>> e[3].append('e3c')
    >>> q
    [1, 2, 3, ['a', 'b', 'w3c']]
    >>> w
    [1, 2, 3, ['a', 'b', 'w3c'], 4]
    >>> e
    [1, 2, 3, ['a', 'b', 'e3c'], '5e']

    有思考的程序猿,看到这里就会提出一个问题。为什么要有浅拷贝和深拷贝呢?它们分别是怎样工作的?在奇妙的网络上,对这个问题有回答,请參考以下两个连接内容:
  • 相关阅读:
    python:利用asyncio进行快速抓取
    os.path.exists(path) 和 os.path.lexists(path) 的区别
    isdigit()判断是不是数字
    switf资源
    51cto培训课程
    51cto运维培训课程
    Python: 在Unicode和普通字符串之间转换
    VC++ CopyFile函数使用方法
    Eclipse断点调试
    AFNetworking2.0后 进行Post请求
  • 原文地址:https://www.cnblogs.com/mqxnongmin/p/10545843.html
Copyright © 2011-2022 走看看