copy和deepcopy

总述

先说明一下,这是python中用来表示复制的概念

总结一下:

如果一个集合中的元素是字符串,copy之后则是两个互不相干的新集合,内存地址也不一样,修改任意一个另一个不会做出改变

但是如果其中的元素有数组的话,那么情况就不一样了

copy后虽然集合是两个完全新的集合,但是集合中的数组指向的是同一个内存地址,在此集合中对其中的数组数据进行修改,另一个集合中的元素是数组的内容也会改变

如果想完完全全独立出来是两个独立的集合,就得使用deepcopy而不是copy

仔细品

如果你够聪明听懂了,就可以关掉文章去耍了(使用方式在之后)

否则看以下操作实例

操作实例

看 仔 细 一 点

·> > > x = {" name":" qiwsir", "lang":[" python", "java", "c"]} 

·> > > y = x.copy() 

·> > > y {' lang': [' python', 'java', 'c'], 'name': 'qiwsir'} 

·> > > id( x) 3072241012L 

·> > > id( y) 3072241284L 

y 是 从 x 拷 贝 过 来 的, 两 个 在 内 存 中 是 不 同 的 对 象。

·> > > y[" lang"]. remove(" c") 

在 y 所 对 应 的 字 典 对 象 中, 键" lang" 的 值 是 一 个 列 表, 为[’ python’,’ java’,’ c’], 这 里 用 remove() 删 除 其 中 的 一 个 元 素" c"。 删 除 之 后, 这 个 列 表 变 为:[’ python’,’ java’]。

·> > > y 

{' lang': [' python', 'java'], 'name': 'qiwsir'}

那 么, x 所 对 应 的 字 典 中, 这 个 列 表 变 化 了 吗? 应 该 没 有 变 化, 因 为 按 照 前 面 所 讲 的, 它 是 另 外 一 个 对 象, 两 个 互 不 干 扰。

·> > > x 

{' lang': [' python', 'java'], 'name': 'qiwsir'}

仔 细 观 察, 是 不 是 有 点 出 乎 意 料 呢? 我 没 有 作 弊 哦。 如 果 不 信, 就 按 照 操 作 自 己 在 交 互 模 式 中 试 试, 是 不 是 也 能 够 得 到 这 个 结 果 呢? 这 是 为 什 么? 但 是, 如 果 要 操 作 另 外 一 个 键 值 对:

·> > > y[" name"] = "laoqi" 

·> > > y 

{' lang': [' python', 'java'], 'name': 'laoqi'} 

·> > > x 

{' lang': [' python', 'java'], 'name': 'qiwsir'} 

前 面 所 说 的 原 理 是 有 效 的, 为 什 么 当 值 是 列 表 的 时 候 就 不 奏 效 了 呢? 要 破 解 这 个 迷 局 还 得 用 id():

·> > > id( x) 3072241012L 

·> > > id( y) 3072241284L

x 和 y 对 应 着 两 个 不 同 的 对 象, 的 确 如 此。 但 这 个 对 象( 字 典) 是 由 两 个 键 值 对 组 成 的, 其 中 一 个 键 的 值 是 列 表。

·> > > id( x[" lang"]) 3072243276L 

·> > > id( y[" lang"]) 3072243276L 

发 现 了 这 样 一 个 事 实: 列 表 是 同 一 个 对 象。 但 是, 作 为 字 符 串 为 值 的 那 个 键 值 对 分 属 不 同 的 对 象。

·> > > id( x[" name"]) 3072245184L

·> > > id( y[" name"]) 3072245408L 
解释分析

这 个 事 实 就 说 明 了 为 什 么 修 改 一 个 列 表, 另 外 一 个 也 跟 着 修 改; 而 修 改 一 个 字 符 串, 另 外 一 个 不 跟 随 的 原 因 了。

但 是, 似 乎 还 没 有 解 开 深 层 的 原 因。 深 层 的 原 因 与 Python 存 储 的 对 象 类 型( 在 不 少 地 方 也 用“ 数 据 类 型” 的 说 法, 其 实 两 者 是 一 样 的,“ 对 象” 和“ 数 据” 在 Python 中 等 同, 不 用 区 分) 特 点 有 关, Python 只 存 储 基 本 类 型 的 数 据, 比 如 int、 str, 对 于 不 是 基 础 类 型 的, 比 如 字 典 的 值 是 列 表, Python 不 会 在 被 复 制 的 那 个 对 象 中 重 新 存 储, 而 是 用 引 用 的 方 式, 指 向 原 来 的 值。

通 俗 地 说, Python 在 所 执 行 的 复 制 动 作 中, 如 果 是 基 本 类 型 的 数 据, 就 在 内 存 中 重 新 建 个 窝, 如 果 不 是 基 本 类 型 的, 就 不 新 建 窝 了, 而 是 用 标 签 引 用 原 来 的 窝。

即 如 果 比 较 简 单, 随 便 建 立 新 窝 即 可; 但 是, 如 果 对 象 太 复 杂 了, 就 别 费 劲 了, 还 是 引 用 一 下 原 来 的 省 事。

所 以, 把 用 copy() 实 现 的 拷 贝 称 之 为“ 浅 拷 贝”( 不 仅 Python, 很 多 语 言都 有“ 浅 拷 贝”。 顾 名 思 义, 没 有 解 决 深 层 次 问 题。 言 外 之 意, 还 有 能 够 解 决 深 层 次 问 题 的 方 法)。

与“ 浅 拷 贝” 对 应, 在 Python 中, 还 有 一 个“ 深 拷 贝”( deep copy)。 不 过, 要 用 import 导 入 一 个 模 块。

deepcopy使用方式
·> > > import copy 

·> > > z = copy.deepcopy( x)

·> > > z 

{' lang': [' python', 'java'], 'name': 'qiwsir'} 

用 copy.deepcopy() 深 拷 贝 了 一 个 新 的 副 本, 用 id() 来 勘 察 一 番:

·> > > id( x[" lang"]) 

3072243276L 

·> > > id( z[" lang"]) 

3072245068L

果 然 是 另 外 一 个“ 窝”, 不 是 引 用 了。 如 果 按 照 这 个 结 果, 修 改 其 中 一 个 列 表 中 的 元 素, 应 该 就 不 影 响 另 外 一 个 了。

·> > > x 

{' lang': [' python', 'java'], 'name': 'qiwsir'} 

·> > > x[" lang"]. remove(" java") 

·> > > x 

{' lang': [' python'], 'name': 'qiwsir'}

·> > > z 

{' lang': [' python', 'java'], 'name': 'qiwsir'} 

果 然 如 此, 再 试 试 才 过 瘾 呀。

·> > > x[" lang"]. append(" c + +") 

·> > > x {' lang': [' python', 'c + +'], 'name': 'qiwsir'} 

这 就 是 所 谓 的 浅 拷 贝 和 深 拷 贝。

  • 10
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值