Google 网上论坛不再支持新的 Usenet 帖子或订阅项。历史内容仍可供查看。

Deeper copy than deepcopy

已查看 3 次
跳至第一个未读帖子

Scott Pakin

未读,
2009年10月27日 16:01:522009/10/27
收件人
copy.deepcopy apparently preserves multiple references to the same object:

$ python
Python 2.5.2 (r252:60911, Jan 4 2009, 17:40:26)
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import copy
>>> d = [1,2,3]
>>> r = copy.deepcopy([d]*3)
>>> r
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
>>> r[1][2] = 999
>>> d
[1, 2, 3]
>>> r
[[1, 2, 999], [1, 2, 999], [1, 2, 999]]
>>>

I wanted to wind up with r being [[1, 2, 3], [1, 2, 999], [1, 2, 3]].
What's the right way to construct r as a list of *independent* d lists?

Thanks,
-- Scott

Cameron Simpson

未读,
2009年10月27日 17:23:542009/10/27
收件人 Scott Pakin、pytho...@python.org

Well, you would need to write your own. But consider this:

x = [1, 2]
x.append(x)

Your deepercopy() function will explode.

Probably the best method is to pre-munge the list you pass to deepcopy:

d = [1,2,3]
d3 = [d]*3
# pre-copy the multiple references
d3deeper = [ list(d3i) for d3i in d3 ]
r = copy.deepcopy(d3deeper)

You can see this requires special knowledge of the structure you're
copying though.
--
Cameron Simpson <c...@zip.com.au> DoD#743
http://www.cskk.ezoshosting.com/cs/

The mere existence of a problem is no proof of the existence of a solution.
- Yiddish Proverb

Cameron Simpson

未读,
2009年10月27日 17:43:092009/10/27
收件人 Scott Pakin、pytho...@python.org
On 28Oct2009 08:23, I wrote:
| | I wanted to wind up with r being [[1, 2, 3], [1, 2, 999], [1, 2, 3]].
| | What's the right way to construct r as a list of *independent* d lists?
|
| Well, you would need to write your own. But consider this:
| x = [1, 2]
| x.append(x)
| Your deepercopy() function will explode.

I've thought of a comprimise that would work automatically: deepcopy
tracks all the objects in the structure and replicates their multiple
uses. For your purposes, you could write a version of deepcopy that did
a depth-first recursion and only tracked the ancestor objects.

That way the above x.append(x) recursive list would not duplicate the
inner "x", but an "x" in two subbranches of a structure _would_ be
replicated i.e. this:

x = [1,2]
y = [x, x]

would get two independent "x"s.

However, it would still mean a recursive structure would get non-independent
"x"s. Which is necessary to avoid an infinite copy but breaks your
requirement.

Every technical corrigendum is met by an equally troublesome new defect report.
- Norman Diamond <dia...@jit.dec.com>

Gary Herron

未读,
2009年10月27日 18:16:152009/10/27
收件人 pytho...@python.org

Try this:

>>>
>>> d = [1,2,3]
>>> r = [[x for x in d] for i in range(3)]


>>> r[1][2] = 999

>>> r


[[1, 2, 3], [1, 2, 999], [1, 2, 3]]

Gary Herron

Steven D'Aprano

未读,
2009年10月27日 20:22:032009/10/27
收件人
On Tue, 27 Oct 2009 15:16:15 -0700, Gary Herron wrote:

> Try this:
>
>
> >>> d = [1,2,3]
> >>> r = [[x for x in d] for i in range(3)]
> >>> r[1][2] = 999
> >>> r
> [[1, 2, 3], [1, 2, 999], [1, 2, 3]]


[x for x in d] is better written as d[:]


--
Steven

Scott Pakin

未读,
2009年10月28日 12:31:512009/10/28
收件人
Thanks everyone! The list-comprehension approach should work in my case
as I know a priori that my data structure is finite. Still, it'd be
awfully convenient for Python's copy module to offer a copy.deepercopy
function -- even if it comes with the caveat that it will explode if
given a data structure with backlinks.

Regards,
-- Scott

0 个新帖子