36

Pythonコードで使用されているリストスライス構文が次のように表示されることがあります。

newList = oldList[:]

確かにこれは次と同じです:

newList = oldList

それとも私は何かが足りないのですか?

4

5 に答える 5

52

[:] Shallowはリストをコピーし、元のリストメンバーへの参照を含むリスト構造のコピーを作成します。これは、コピーに対する操作がオリジナルの構造に影響を与えないことを意味します。ただし、リストメンバーに何かを行った場合でも、両方のリストがそれらを参照しているため、元のメンバーからメンバーにアクセスすると、更新が表示されます。

ディープコピーは、すべてのリストメンバーのコピーも作成します。

以下のコードスニペットは、動作中の浅いコピーを示しています。

# ================================================================
# === ShallowCopy.py =============================================
# ================================================================
#
class Foo:
    def __init__(self, data):
        self._data = data

aa = Foo ('aaa')
bb = Foo ('bbb')

# The initial list has two elements containing 'aaa' and 'bbb'
OldList = [aa,bb]
print OldList[0]._data

# The shallow copy makes a new list pointing to the old elements
NewList = OldList[:]
print NewList[0]._data

# Updating one of the elements through the new list sees the
# change reflected when you access that element through the
# old list.
NewList[0]._data = 'xxx'
print OldList[0]._data

# Updating the new list to point to something new is not reflected
# in the old list.
NewList[0] = Foo ('ccc')
print NewList[0]._data
print OldList[0]._data

Pythonシェルで実行すると、次のトランスクリプトが得られます。古いオブジェクトのコピーで作成されたリストを見ることができます。オブジェクトの1つは、古いリストを介して参照によって状態を更新できます。更新は、オブジェクトが古いリストを介してアクセスされたときに確認できます。最後に、新しいリストが別のオブジェクトを参照しているため、新しいリストで参照を変更しても、古いリストには反映されないことがわかります。

>>> # ================================================================
... # === ShallowCopy.py =============================================
... # ================================================================
... #
... class Foo:
...     def __init__(self, data):
...         self._data = data
...
>>> aa = Foo ('aaa')
>>> bb = Foo ('bbb')
>>>
>>> # The initial list has two elements containing 'aaa' and 'bbb'
... OldList = [aa,bb]
>>> print OldList[0]._data
aaa
>>>
>>> # The shallow copy makes a new list pointing to the old elements
... NewList = OldList[:]
>>> print NewList[0]._data
aaa
>>>
>>> # Updating one of the elements through the new list sees the
... # change reflected when you access that element through the
... # old list.
... NewList[0]._data = 'xxx'
>>> print OldList[0]._data
xxx
>>>
>>> # Updating the new list to point to something new is not reflected
... # in the old list.
... NewList[0] = Foo ('ccc')
>>> print NewList[0]._data
ccc
>>> print OldList[0]._data
xxx
于 2008-11-27T13:00:31.973 に答える
49

NXC が言ったように、Python の変数名は実際にはオブジェクトを指しており、メモリ内の特定の場所を指しているわけではありません。

newList = oldListは、同じオブジェクトを指す 2 つの異なる変数を作成するため、変更oldListすると変更も行われますnewList

ただし、 を実行するnewList = oldList[:]と、リストが「スライス」され、新しいリストが作成されます。のデフォルト値[:]は 0 とリストの最後なので、すべてをコピーします。したがって、最初のリストに含まれるすべてのデータを含む新しいリストが作成されますが、両方を変更しても、もう一方を変更する必要はありません。

于 2008-11-27T13:13:58.483 に答える
12

すでに回答されているので、簡単なデモを追加します。

>>> a = [1, 2, 3, 4]
>>> b = a
>>> c = a[:]
>>> b[2] = 10
>>> c[3] = 20
>>> a
[1, 2, 10, 4]
>>> b
[1, 2, 10, 4]
>>> c
[1, 2, 3, 20]
于 2008-11-27T13:40:50.487 に答える
4

Pythonの「a=b」が「bをaにコピーする」ことを意味するとは決して考えないでください。両側に変数がある場合、それを実際に知ることはできません。代わりに、「bに追加の名前aを付けてください」と考えてください。

bが不変オブジェクト(数値、タプル、文字列など)の場合、はい、その効果はコピーを取得することです。しかし、それは、不変(読み取り専用変更不可、またはWORMと呼ばれるべきだった)を扱う場合、定義上、常にコピーを取得するためです。

bが可変である場合、真のコピーがあることを確認するために、常に何か特別なことをする必要があります常に。リストを使用すると、スライスと同じくらい簡単です:a = b [:]。

可変性は、これが理由でもあります。

def myfunction(mylist=[]): 
    pass

...あなたが思っていることを完全には行いません。

Cのバックグラウンドを使用している場合:「=」の左側は常にポインターです。すべての変数は常にポインターです。変数をリストに入れる場合:a = [b、c]、aが指すリストにbとcが指す値へのポインターを置きます。次にa[0]= dに設定すると、位置0のポインターは、dが指すものを指します。

copy-moduleも参照してください:http:  //docs.python.org/library/copy.html

于 2008-11-27T13:45:58.730 に答える
-2

浅いコピー: (メモリのチャンクをある場所から別の場所にコピーします)

a = ['one','two','three']

b = a[:]

b[1] = 2

print id(a), a #Output: 1077248300 ['one', 'two', 'three']
print id(b), b #Output: 1077248908 ['one', 2, 'three']

ディープ コピー: (オブジェクト参照をコピーします)

a = ['one','two','three']

b = a

b[1] = 2


print id(a), a #Output: 1077248300 ['one', 2, 'three']
print id(b), b #Output: 1077248300 ['one', 2, 'three']
于 2010-02-08T10:30:39.237 に答える