2012-04-27 18 views
1

私はちょうどプログラミングを始めました。そして、「コンピュータ科学者のように考える方法」を通して、Pythonのために働いています。クローニングとディープコピーの違いは?

def add_column(matrix): 

    """ 
    >>> m = [[0, 0], [0, 0]] 
    >>> add_column(m) 
    [[0, 0, 0], [0, 0, 0]] 
    >>> n = [[3, 2], [5, 1], [4, 7]] 
    >>> add_column(n) 
    [[3, 2, 0], [5, 1, 0], [4, 7, 0]] 
    >>> n 
    [[3, 2], [5, 1], [4, 7]] 
    """ 

上記のコードはdoctestのパスを作成する必要があります。私は、第9章でエクササイズに来たまで、私は何の問題もありませんでした。私は最後のテストに立ち往生していました。

x = len(matrix) 

matrix2 = [d[:] for d in matrix] 
for z in range(x): 
    matrix2[z] += [0] 
return matrix2 

私の質問はこれです:なぜ二行目は、することはできません。この行が所定の位置にある

matrix2 = matrix[:] 

元のリストを編集します私は以下の通りであるソリューションを、見上げ加算要素を含める。 「How to be ..」ガイドは、元のリストに影響を与えずに編集可能な新しいリストをクローン作成のように発音させます。それが本当なら、ここで何が起こっているの?私が使用している場合:

matrix2 = copy.deepcopy(matrix) 

すべてが正常に動作しますが、私は、クローニングは失敗するだろうという印象の下ではなかった... 任意の助けをいただければ幸いです!

答えて

0

ネストされたリストがあるとします。コピーすると、ネストされたリストへの参照のみがコピーされます。

>>> a = [1] 
>>> b = [2] 
>>> c = [a, b] 
>>> c 
[[1], [2]] 
>>> d = c[:] 
>>> d 
[[1], [2]] 
>>> d[1].append(2) 
>>> d 
[[1], [2, 2]] 
>>> c 
[[1], [2, 2]] 

はどこ、copy.deepcopy()と同じように:

>>> d = copy.deepcopy(c) 
>>> d[1].append(2) 
>>> c 
[[1], [2]] 
>>> d 
[[1], [2, 2]] 

これは、任意の可変項目についても同様です。 copy.deepcopy()はコピーされていることを確認しようとします。

d = c[:]を使用してリストをコピーすることは、とにかく非常に明確な構文ではありません。もっと良い解決策はd = list(c)です(list()は、別のリストを含む任意の反復可能リストから新しいリストを返します)。明らかに、明らかに、copy.copy()です。あなたのケースでは

+0

感謝。行列の離散コピーを作成したいが、入れ子リストを同じオブジェクトを参照するようにしたいという理由は何か?私はそれが混乱以外の何かになることを予見するプロセスには十分ではありません。 – Alxmrg

+0

これは、設計の決定が少なく、Pythonの仕組みの影響もあります。 Pythonで割り当てるときはいつでも、あなたはオブジェクトをコピーしません、あなたは単にそれへの参照として変数を割り当てます。他の方法で任意に行うことは意味がありません。 –

1

は、matrixは、他のリストが含まれているので、あなたはmatrix[:]を行うときに、あなたは他のリストへの参照が含まれているmatrixを、クローニングされています。それらもクローン化されていません。したがって、これらを編集すると、元のmatrixリストには同じままです。ただし、コピーにアイテムを追加すると(matrix[:])、元のリストには追加されません。

これを視覚化するには、id関数を使用して、オブジェクトごとに固有の番号を返します。the docsを参照してください。

a = [[1,2], [3,4], 5] 
print 'id(a)', id(a) 
print '>>', [id(i) for i in a] 

not_deep = a[:] 
# Notice that the ids of a and not_deep are different, so it's not the same list 
print 'id(not_deep)', id(not_deep) 
# but the lists inside of it have the same id, because they were not cloned! 
print '>>', [id(i) for i in not_deep] 

# Just to prove that a and not_deep are two different lists 
not_deep.append([6, 7]) 
print 'a items:', len(a), 'not_deep items:', len(not_deep) 

import copy 
deep = copy.deepcopy(a) 
# Again, a different list 
print 'id(deep)', id(deep) 
# And this time also all the nested list (and all mutable objects too, not shown here) 
# Notice the different ids 
print '>>', [id(i) for i in deep] 

そして出力:私はこの時点で理解だと思うヘルプ - のための

id(a) 36169160 
>> [36168904L, 35564872L, 31578344L] 
id(not_deep) 35651784 
>> [36168904L, 35564872L, 31578344L] 
a items: 3 not_deep items: 4 
id(deep) 36169864 
>> [36168776L, 36209544L, 31578344L] 
+0

私は理解していると思う...だから "行列"にネストされたリストが含まれていなければ、クローンするレベルが1つしかないので大丈夫でしょうか?そしてそれがdeepcopyが働く理由です。それはすべてのレベルを下にコピーしています。ネストされたリストさえも... "How to be ..."は、もっと理にかなったアプローチに進む前に、最も基本的な概念を完全に教えようとしていました。それはちょうど私を混乱させてしまった。ありがとう! – Alxmrg

+0

修正。 100%:D – jadkik94

関連する問題