先说明一下,这是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 导 入 一 个 模 块。
·> > > 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'}
这 就 是 所 谓 的 浅 拷 贝 和 深 拷 贝。