문제

때때로 파이썬 코드에서 사용 된 목록 슬라이스 구문을 다음과 같이 볼 수 있습니다.

newList = oldList[:]

확실히 이것은 다음과 같습니다.

newList = oldList

아니면 내가 뭔가를 놓치고 있습니까?

도움이 되었습니까?

해결책

NXC와 마찬가지로 Python 변수 이름은 실제로 객체를 가리키며 메모리의 특정 지점이 아닙니다.

newList = oldList 따라서 동일한 객체를 가리키는 두 가지 변수를 생성하므로 변경됩니다. oldList 또한 변할 것입니다 newList.

그러나 당신이 할 때 newList = oldList[:], 그것은 목록을 "슬라이스"하고 새 목록을 만듭니다. 기본값 [:] 0이고 목록의 끝이므로 모든 것을 복사합니다. 따라서 첫 번째 데이터에 포함 된 모든 데이터가 포함 된 새 목록을 작성하지만 둘 다 변경하지 않고도 변경 될 수 있습니다.

다른 팁

[:] 얕은 사본 목록, 원래 목록 멤버에 대한 참조를 포함하는 목록 구조의 사본을 작성합니다. 이것은 사본의 작업이 원본의 구조에 영향을 미치지 않음을 의미합니다. 그러나 목록 멤버에게 무언가를하는 경우 두 목록 모두에도 여전히 참조하므로 멤버가 원본을 통해 액세스 할 경우 업데이트가 표시됩니다.

딥 카피 모든 목록 멤버의 사본도 만들 것입니다.

아래 코드 스 니펫은 얕은 사본을 보여줍니다.

# ================================================================
# === 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

파이썬 쉘에서 실행하면 다음 성적표가 제공됩니다. 우리는 오래된 물체의 사본으로 목록이 만들어지는 것을 볼 수 있습니다. 객체 중 하나는 이전 목록을 통해 참조로 상태를 업데이트 할 수 있으며 기존 목록을 통해 개체에 액세스 할 때 업데이트를 볼 수 있습니다. 마지막으로, 새 목록이 다른 객체를 참조하기 때문에 새 목록에서 참조를 변경하는 것은 이전 목록에 반영되지 않는 것으로 볼 수 있습니다.

>>> # ================================================================
... # === 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

이미 대답을 받았을 때 간단한 데모를 추가하겠습니다.

>>> 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]

파이썬에서 'a = b'는 'copy b to a'를 의미한다고 생각하지 마십시오. 양쪽에 변수가 있다면 실제로 그것을 알 수 없습니다. 대신, '추가 이름 A'라고 생각하십시오.

B가 불변의 물체 인 경우 (숫자, 튜플 또는 문자열과 같은), 그렇습니다. 효과는 사본을 얻는 것입니다. 그러나 그것은 당신이 불변을 다룰 때 (아마도 부름을 받았을 것입니다. 만 읽으십시오, 변경할 수 없습니다 또는 벌레) 너 언제나 정의상 사본을 받으십시오.

B가 변이 가능하다면, 당신은 당신입니다 진정한 사본이 있는지 확인하려면 항상 추가 작업을 수행해야합니다.. 언제나. 목록을 사용하면 슬라이스만큼 간단합니다. a = b [:].

돌연변이는 또한 다음과 같은 이유입니다.

def myfunction(mylist=[]): 
    pass

... 당신이 생각하는 것을 잘하지 않습니다.

C-Background에서 온 경우 : '='의 남은 것은 항상 포인터입니다. 모든 변수는 항상 포인터입니다. 목록에 변수를 넣으면 A = [B, C], A가 지적한 목록에서 B와 C가 지적한 값에 포인터를 넣습니다. 그런 다음 [0] = D를 설정하면 위치 0의 포인터는 이제 D가 가리키는 모든 것을 가리키고 있습니다.

카피 모드를 참조하십시오 :http://docs.python.org/library/copy.html

얕은 사본 : (한 위치에서 다른 위치로 메모리 덩어리를 복사합니다)

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']
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top