파이썬 목록 조각에서 할당은 어떻게 작동합니까?


99

Python 문서에 따르면 목록을 분할하면 새 목록이 반환됩니다.
이제 "새"목록이 반환되면 "슬라이스에 할당"과 관련된 다음과 같은 의심이 있습니다.

a = [1, 2, 3]
a[0:2] = [4, 5]
print a

이제 출력은 다음과 같습니다.

[4, 5, 3] 
  1. 무언가를 반환하는 것이 어떻게 표현의 왼쪽에 올 수 있습니까?
  2. 예, 문서를 읽었는데 목록을 분할하면 "새"목록이 반환되기 때문에 가능하다고합니다. 원래 목록이 수정되는 이유는 무엇입니까? 나는 그 뒤에있는 메커니즘을 이해할 수 없습니다.

@Mark Longair 죄송 합니다만 코드가 출력이 아닌 형식화되어야한다고 생각했습니다
Kartik Anand

2

7
무엇 a[0] = 4을 할 것인지 이해 합니까?
Josh Lee

1
@KartikAnand Slice 할당은 새 목록이 생성되지 않는 특수 시나리오입니다. 의 왼쪽에 이름 바인딩없이 객체를 생성하는 것은 이치에 맞지 않습니다 =. 그래서 이것을 잘못된 구문으로 버리는 대신 파이썬은 여러분이 기대할 수있는 것과 비슷한 것으로 바꾸어줍니다. 파이썬에는 참조가 없기 때문에 슬라이스 결과가 원래 목록을 변경하도록 작동하지 않습니다. 당신은 사본을 얻습니다. 애플리케이션에 대한 더 많은 정보를 제공했다면 'pythonic'방식으로 작업을 수행하는 데 더 나은 도움을 드릴 수 있습니다. :)
Casey Kuball

1
@Darthfett 나는 지금 어떤 응용 프로그램도 작업하고 있지 않고 오히려 손을 더럽 히기 시작하기 전에 파이썬을 가르치고 있습니다 :)
Kartik Anand

답변:


114

매우 유사한 구문을 사용하는 두 가지 별개의 작업을 혼동하고 있습니다.

1) 슬라이스 :

b = a[0:2]

이렇게하면의 슬라이스 사본이 만들어져에 a할당됩니다 b.

2) 슬라이스 할당 :

a[0:2] = b

이렇게 하면의 조각이 의 내용으로 바뀝니다 .ab

구문은 비슷하지만 (설계 상 상상합니다!) 두 가지 다른 작업입니다.


4
그게 내 의심입니다. 두 번째 경우에는 왜 새로운 목록이 아닌가 ??
Kartik Anand

11
@KartikAnand 아니기 때문에. 그것은 언어가 지정하는 것이 아닙니다.
Marcin

명확하게 말하면, "takes a slice of"는 혼동의 일부가 발생하는 "한 조각의 복사본 만들기"를 의미합니다.
Mark Ransom

2
@KartikAnand : 기본적으로 그렇습니다. 통역사는 어느 것이 무엇인지 알고 적절하게 처리합니다.
NPE

1
@Dubslow : itertools 모듈 을 사용하면 됩니다. 귀하의 경우에 대한 함수 사용 islice 과를, start=1, stop=None. 이것은 복사를 피하고 지연 평가를 사용합니다 (귀하의 경우 원래 목록에 대한 지연 액세스).
Spiros

66

연산자 a의 왼쪽에 지정 하면 현재 컨텍스트 의 이름 이 새 값을 가리 키도록 변경하는 =Python의 일반 할당 을 사용하는 것 a입니다. a가리키는 이전 값은 변경되지 않습니다 .

연산자 a[0:2]의 왼쪽에 지정 =하면 Python에 Slice Assignment 를 사용하고 싶다고 말하는 것 입니다. 슬라이스 할당은 목록에 대한 특수 구문으로, 목록에서 내용을 삽입, 삭제 또는 바꿀 수 있습니다.

삽입 :

>>> a = [1, 2, 3]
>>> a[0:0] = [-3, -2, -1, 0]
>>> a
[-3, -2, -1, 0, 1, 2, 3]

삭제 :

>>> a
[-3, -2, -1, 0, 1, 2, 3]
>>> a[2:4] = []
>>> a
[-3, -2, 1, 2, 3]

교체 :

>>> a
[-3, -2, 1, 2, 3]
>>> a[:] = [1, 2, 3]
>>> a
[1, 2, 3]

노트 :

슬라이스의 길이는 할당 된 시퀀스의 길이와 다를 수 있으므로 타겟 시퀀스가 ​​허용하는 경우 타겟 시퀀스의 길이를 변경합니다. - 소스

Slice Assignment는 Tuple Unpacking 과 유사한 기능을 제공합니다 . 예를 들어 a[0:1] = [4, 5]는 다음과 같습니다.

# Tuple Unpacking
a[0], a[1] = [4, 5]

Tuple Unpacking을 사용하면 비 순차 목록을 수정할 수 있습니다.

>>> a
[4, 5, 3]
>>> a[-1], a[0] = [7, 3]
>>> a
[3, 5, 7]

그러나 튜플 압축 해제는 요소를 삽입하거나 제거 할 수 없으므로 교체로 제한됩니다.

이 모든 작업 전후 a는 동일한 정확한 목록입니다. 파이썬은 단순히 목록을 제자리에서 수정하기 위해 멋진 구문 설탕을 제공합니다.


6
유사하지만 동일하지는 않습니다. 왼쪽과 오른쪽의 요소 수가 같지 않을 수 있기 때문입니다.
Mark Ransom

@MarkRansom 그것은 훌륭한 포인트입니다, 나는 이것을 명백하게하기 위해 더 많은 정보를 추가했습니다.
Casey Kuball

2
a[:] = some_list동등 a = some_list[:]또는 a = some_list?
jadkik94

2
@ jadkik94 둘 다 아닙니다. a[:] = some_list세트의 모든 요소 a들 될을 some_list. 언급 한 것 중 하나를 수행하면 내용 a이 변경 됩니다. 예 : a = [1, 2, 3] b = a a[:] = [4, 5, 6] a is b. a의 값을 변경 하지 않고 변경하면 마지막 줄은 False가됩니다 .
Casey Kuball

@Darthfett 흥미롭게도, 나는 그렇지 않으면 발견했다 :) 감사합니다.
jadkik94

25

나는 전에 같은 질문을 보았고 언어 사양과 관련이 있습니다. 할당 문 에 따르면 ,

  1. 할당의 왼쪽이 구독이면 Python은 __setitem__해당 개체를 호출 합니다. a[i] = x와 동일합니다 a.__setitem__(i, x).

  2. 할당의 왼쪽 슬라이스 인 경우, 파이썬은 또한 호출 __setitem__하지만, 다른 인수 : a[1:4]=[1,2,3]동일합니다 a.__setitem__(slice(1,4,None), [1,2,3])

그렇기 때문에 '='의 왼쪽에있는 목록 조각이 다르게 동작합니다.


4

할당 작업의 왼쪽을 슬라이스하여 할당 할 항목을 지정합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.