作者why8ther (外八喵)
看板Python
标题Re: [问题] a[1:3]会马上复制吗?
时间Wed Jul 22 10:27:49 2015
※ 引述《why8ther (外八喵)》之铭言:
: 已知:
: b = [2, 3]
: >>> b[0] = 99
: b = [99, 3]
: a = [1, 2, 3, 4]
: 由此可知,黄色那行的值并不会改动到a阵列,而是创造一个副本了
: 我的问题是 :
: 这个副本是(1) 在我呼叫a[1:3]时就被创造了?
: 抑或(2) 直到我改动b[0]才被创造,若不改动就永远参照本来阵列
: 因为最近遇到比较高的性能要求 需要弄清楚@@
: 第一次po文 请大家多多指教
自己回自己的文XDD
其实应该是有实作copy on write的
根据这篇stack overflow
http://goo.gl/XcgHG6
我自己实验也是一样的结果
>>> a = [1,2,3]
>>> b = a[1:3]
>>> id(a[1])
1440535008
>>> id(b[0])
1440535008
>>> b[0] = 123
>>> a
[1, 2, 3]
>>> b
[123, 3]
>>> id(a[1])
1440535008
>>> id(b[0])
1440536944
变得不一样了!!
>>> id(a[2])
1440535024
>>> id(b[1])
但a[2]和b[1]没有被改动,仍是同一个
1440535024
不过虽说是copy on write,但我推测应该还是复制了阵列中每个元素的referance
而不只是阵列本身的referance
推测根据就是上面那行红字。
若本来阵列长度是100,就等於复制了100份的参照。
所以比较适合的状况应该是:
阵列中每个物件很大,但阵列本身较短
反之,若阵列元素很小(像是int)
那复制参照跟直接复制应该就没啥差别惹。
大概是这样
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 140.96.27.107
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/Python/M.1437532071.A.759.html
※ 编辑: why8ther (140.96.27.107), 07/22/2015 10:35:45
2F:→ LiloHuang: 把 reference 拷贝过去,这并不算是 Copy-on-write 07/22 10:51
3F:→ LiloHuang: 毕竟拷贝的行为还是产生了,而且并不是在 write 时拷贝 07/22 10:54
4F:→ LiloHuang: 所以不能称之为是完整的 copy-on-write。 07/22 10:54
5F:→ uranusjr: 这根本就不是 copy-on-write, 无所谓完不完整啊 07/22 11:35
6F:→ uranusjr: 你在 C++ 拷贝 list<int *> 也会有类似行为, 但根本不会 07/22 11:36
7F:→ uranusjr: 有人把它叫做 copy-on-write, 因为它就是单纯的 copy 07/22 11:36
8F:推 LiloHuang: 我必须要修正我的用语,这不是"真正"的 copy-on-write 07/22 11:43
9F:→ LiloHuang: 谢谢 uranusjr 的补充 :) 07/22 11:43
10F:→ LiloHuang: 真正的 copy-on-write 是在 write 时拷贝物件,即便是 07/22 11:45
11F:→ LiloHuang: reference 也要在 write 时才被拷贝,而不是一开始拷贝 07/22 11:45
12F:→ LiloHuang: 如果有一亿个 list elements 搭配 COW,不会有 O(n) 的 07/22 11:46
13F:→ LiloHuang: 拷贝成本存在於建立第二份 list 时 07/22 11:46
14F:→ LiloHuang: 另外之所以我会用是否"完整"的用词是维基百科对於 COW 07/22 11:48
15F:→ LiloHuang: 的定义,某种策略上是有用指标来只到原始版本的 07/22 11:48
17F:→ LiloHuang: 因为真正大家谈及的COW,都是像 fork child process 07/22 11:50
18F:→ LiloHuang: 在还没有修改原始版本前,不应该存在有额外的消耗就是 07/22 11:51
19F:→ LiloHuang: 或者应该说 C++ 拷贝 list<Foobar *> 假设 Foobar 是 07/22 11:52
20F:→ LiloHuang: 成本超高的大物件,在写入时作出副本,也是某种程度的 07/22 11:53
21F:→ LiloHuang: COW,对於该大物件而言。只是 Python 根本就是建立了 07/22 11:53
22F:→ LiloHuang: 新物件,然後把参照给换掉,因为数字是 immutable obj 07/22 11:53
23F:→ LiloHuang: 跟 COW 的策略一点关系都没有,因为新物件不是它建立的 07/22 11:56
24F:→ LiloHuang: 真正的 COW 要是全自动的,对使用者来说是透明无感的。 07/22 12:02
25F:→ LiloHuang: 另外如同维基百科写的 std::string 有 COW 实作 07/22 12:02
26F:→ LiloHuang: 有空的人不仿可以看看实作方法,我相信是拷贝指标 :P 07/22 12:02
27F:推 LiloHuang: 因此用"完整"一词会更好,完整的COW连指标都不会拷贝 07/22 12:06
28F:→ LiloHuang: 但这还是端看实作,跟到底被 COW 的对象是什麽物件而定 07/22 12:07
想一想这样应该真的不算COW...
python的复制本来就只是复制referance
刚刚发文的时候观念突然跑掉...抱歉...
※ 编辑: why8ther (140.96.27.107), 07/22/2015 13:06:45