개봉, 확장 개봉 및 중첩 확장 개봉


105

다음 표현을 고려하십시오. 일부 표현식은 "컨텍스트"를 나타 내기 위해 반복됩니다.

(이것은 긴 목록입니다)

a, b = 1, 2                          # simple sequence assignment
a, b = ['green', 'blue']             # list asqignment
a, b = 'XY'                          # string assignment
a, b = range(1,5,2)                  # any iterable will do


                                     # nested sequence assignment

(a,b), c = "XY", "Z"                 # a = 'X', b = 'Y', c = 'Z' 

(a,b), c = "XYZ"                     # ERROR -- too many values to unpack
(a,b), c = "XY"                      # ERROR -- need more than 1 value to unpack

(a,b), c, = [1,2],'this'             # a = '1', b = '2', c = 'this'
(a,b), (c,) = [1,2],'this'           # ERROR -- too many values to unpack


                                     # extended sequence unpacking

a, *b = 1,2,3,4,5                    # a = 1, b = [2,3,4,5]
*a, b = 1,2,3,4,5                    # a = [1,2,3,4], b = 5
a, *b, c = 1,2,3,4,5                 # a = 1, b = [2,3,4], c = 5

a, *b = 'X'                          # a = 'X', b = []
*a, b = 'X'                          # a = [], b = 'X'
a, *b, c = "XY"                      # a = 'X', b = [], c = 'Y'
a, *b, c = "X...Y"                   # a = 'X', b = ['.','.','.'], c = 'Y'

a, b, *c = 1,2,3                     # a = 1, b = 2, c = [3]
a, b, c, *d = 1,2,3                  # a = 1, b = 2, c = 3, d = []

a, *b, c, *d = 1,2,3,4,5             # ERROR -- two starred expressions in assignment

(a,b), c = [1,2],'this'              # a = '1', b = '2', c = 'this'
(a,b), *c = [1,2],'this'             # a = '1', b = '2', c = ['this']

(a,b), c, *d = [1,2],'this'          # a = '1', b = '2', c = 'this', d = []
(a,b), *c, d = [1,2],'this'          # a = '1', b = '2', c = [], d = 'this'

(a,b), (c, *d) = [1,2],'this'        # a = '1', b = '2', c = 't', d = ['h', 'i', 's']

*a = 1                               # ERROR -- target must be in a list or tuple
*a = (1,2)                           # ERROR -- target must be in a list or tuple
*a, = (1,2)                          # a = [1,2]
*a, = 1                              # ERROR -- 'int' object is not iterable
*a, = [1]                            # a = [1]
*a = [1]                             # ERROR -- target must be in a list or tuple
*a, = (1,)                           # a = [1]
*a, = (1)                            # ERROR -- 'int' object is not iterable

*a, b = [1]                          # a = [], b = 1
*a, b = (1,)                         # a = [], b = 1

(a,b),c = 1,2,3                      # ERROR -- too many values to unpack
(a,b), *c = 1,2,3                    # ERROR - 'int' object is not iterable
(a,b), *c = 'XY', 2, 3               # a = 'X', b = 'Y', c = [2,3]


                                     # extended sequence unpacking -- NESTED

(a,b),c = 1,2,3                      # ERROR -- too many values to unpack
*(a,b), c = 1,2,3                    # a = 1, b = 2, c = 3

*(a,b) = 1,2                         # ERROR -- target must be in a list or tuple
*(a,b), = 1,2                        # a = 1, b = 2

*(a,b) = 'XY'                        # ERROR -- target must be in a list or tuple
*(a,b), = 'XY'                       # a = 'X', b = 'Y'

*(a, b) = 'this'                     # ERROR -- target must be in a list or tuple
*(a, b), = 'this'                    # ERROR -- too many values to unpack
*(a, *b), = 'this'                   # a = 't', b = ['h', 'i', 's']

*(a, *b), c = 'this'                 # a = 't', b = ['h', 'i'], c = 's'

*(a,*b), = 1,2,3,3,4,5,6,7           # a = 1, b = [2, 3, 3, 4, 5, 6, 7]

*(a,*b), *c = 1,2,3,3,4,5,6,7        # ERROR -- two starred expressions in assignment
*(a,*b), (*c,) = 1,2,3,3,4,5,6,7     # ERROR -- 'int' object is not iterable
*(a,*b), c = 1,2,3,3,4,5,6,7         # a = 1, b = [2, 3, 3, 4, 5, 6], c = 7
*(a,*b), (*c,) = 1,2,3,4,5,'XY'      # a = 1, b = [2, 3, 4, 5], c = ['X', 'Y']

*(a,*b), c, d = 1,2,3,3,4,5,6,7      # a = 1, b = [2, 3, 3, 4, 5], c = 6, d = 7
*(a,*b), (c, d) = 1,2,3,3,4,5,6,7    # ERROR -- 'int' object is not iterable
*(a,*b), (*c, d) = 1,2,3,3,4,5,6,7   # ERROR -- 'int' object is not iterable
*(a,*b), *(c, d) = 1,2,3,3,4,5,6,7   # ERROR -- two starred expressions in assignment


*(a,b), c = 'XY', 3                  # ERROR -- need more than 1 value to unpack
*(*a,b), c = 'XY', 3                 # a = [], b = 'XY', c = 3
(a,b), c = 'XY', 3                   # a = 'X', b = 'Y', c = 3

*(a,b), c = 'XY', 3, 4               # a = 'XY', b = 3, c = 4
*(*a,b), c = 'XY', 3, 4              # a = ['XY'], b = 3, c = 4
(a,b), c = 'XY', 3, 4                # ERROR -- too many values to unpack

그러한 표현의 결과를 손으로 올바르게 추론하는 방법은 무엇입니까?


28
솔직히 이것들 대부분은 매일 코드에서 보는 것보다 훨씬 더 복잡합니다. 목록 / 튜플 압축 풀기의 기본 사항을 배우면 괜찮을 것입니다.
Rafe Kettler 2011 년

2
이들은 재귀 적이라는 점에 유의하십시오. 따라서 처음 몇 명만 이해하면 모든 것을 처리 할 수 ​​있습니다. 예를 들어 * (* a, b)를 * x로 바꾸고, x가 압축을
푸는 것을 파악한 다음

4
@greengit 저는 Python에 대한 고급 지식을 가지고 있다고 생각하고 일반적인 규칙을 알고 있습니다. :) 모든 경우를 알 필요는 없습니다. 때로는 인터프리터를 실행하고 무언가를 테스트해야합니다.
Rafe Kettler

와우 좋은 목록. 나는 a, *b = 1, 2, 3포장 풀기 의 종류에 대해 정말로 몰랐다 . 그러나 이것은 Py3k 맞습니까?
Niklas R

답변:


113

이 게시물의 길이에 대해 죄송하지만 완전성을 선택하기로 결정했습니다.

몇 가지 기본 규칙을 알고 나면 일반화하는 것이 어렵지 않습니다. 몇 가지 예를 들어 설명하기 위해 최선을 다하겠습니다. 이러한 "손으로"평가하는 것에 대해 이야기하고 있으므로 몇 가지 간단한 대체 규칙을 제안하겠습니다. 기본적으로 모든 이터 러블이 동일한 방식으로 형식화되면 표현식을 이해하는 것이 더 쉬울 수 있습니다.

압축을 풀기 위해서만 다음 대체가 오른쪽에서 유효합니다 =(예 : rvalues ).

'XY' -> ('X', 'Y')
['X', 'Y'] -> ('X', 'Y')

값의 압축이 풀리지 않는 경우 대체를 실행 취소합니다. (자세한 설명은 아래를 참조하십시오.)

또한 "네이 키드"쉼표가 표시되면 최상위 튜플이있는 것처럼 가장하십시오. 왼쪽과 오른쪽 모두에서이 작업을 수행합니다 (예 : lvaluesrvalues ).

'X', 'Y' -> ('X', 'Y')
a, b -> (a, b)

이러한 간단한 규칙을 염두에두고 몇 가지 예를 들면 다음과 같습니다.

(a,b), c = "XY", "Z"                 # a = 'X', b = 'Y', c = 'Z'

위의 규칙을 적용하여로 변환 "XY"하고 ('X', 'Y')괄호 안의 쉼표를 덮습니다.

((a, b), c) = (('X', 'Y'), 'Z')

여기의 시각적 일치는 할당이 어떻게 작동하는지 상당히 분명하게 만듭니다.

다음은 잘못된 예입니다.

(a,b), c = "XYZ"

위의 대체 규칙에 따라 다음과 같은 결과를 얻습니다.

((a, b), c) = ('X', 'Y', 'Z')

이것은 분명히 잘못된 것입니다. 중첩 된 구조가 일치하지 않습니다. 이제 약간 더 복잡한 예제에서 어떻게 작동하는지 살펴 보겠습니다.

(a,b), c, = [1,2],'this'             # a = '1', b = '2', c = 'this'

위의 규칙을 적용하면

((a, b), c) = ((1, 2), ('t', 'h', 'i', 's'))

그러나 이제는 'this'압축이 풀리지 않고 c. 그래서 우리는 대체를 취소합니다.

((a, b), c) = ((1, 2), 'this')

이제 c튜플을 래핑 할 때 어떤 일이 발생하는지 살펴 보겠습니다 .

(a,b), (c,) = [1,2],'this'           # ERROR -- too many values to unpack

된다

((a, b), (c,)) = ((1, 2), ('t', 'h', 'i', 's'))

다시 말하지만 오류는 분명합니다. c은 더 이상 네이 키드 변수가 아니라 시퀀스 내의 변수이므로 오른쪽에있는 해당 시퀀스가 (c,). 하지만 시퀀스의 길이가 다르기 때문에 오류가 있습니다.

이제 *연산자를 사용하여 확장 된 포장을 풀 수 있습니다. 이것은 조금 더 복잡하지만 여전히 매우 간단합니다. 앞에 오는 변수 *는 변수 이름에 할당되지 않은 해당 시퀀스의 항목을 포함하는 목록이됩니다. 매우 간단한 예부터 시작합니다.

a, *b, c = "X...Y"                   # a = 'X', b = ['.','.','.'], c = 'Y'

이것은

(a, *b, c) = ('X', '.', '.', '.', 'Y')

이를 분석하는 가장 간단한 방법은 끝에서 작업하는 것입니다. 'X'이에 할당 a되고 'Y'에 할당되었습니다 c. 시퀀스의 나머지 값은 목록에 배치되고에 할당됩니다 b.

같은 Lvalues (*a, b)하고 (a, *b)위의 단지 특별한 경우입니다. *모호하기 때문에 하나의 lvalue 시퀀스 내에 두 개의 연산자를 사용할 수 없습니다 . 어디 값은 다음과 같이 갈 것입니다 (a, *b, *c, d)에 - bc? 잠시 후 중첩 된 경우를 고려하겠습니다.

*a = 1                               # ERROR -- target must be in a list or tuple

여기서 오류는 매우 자명합니다. 대상 ( *a)은 튜플에 있어야합니다.

*a, = (1,2)                          # a = [1,2]

알몸 쉼표가 있기 때문에 작동합니다. 규칙 적용 중 ...

(*a,) = (1, 2)

이외의 변수가 없기 때문에 *a, *ar- 수치 시퀀스 내의 모든 값을 slurps. 를 (1, 2)단일 값으로 바꾸면 어떻게됩니까?

*a, = 1                              # ERROR -- 'int' object is not iterable

된다

(*a,) = 1

여기서도 오류는 자명합니다. 시퀀스가 아닌 것은 풀 수 없으며 풀어야 할 것이 *a필요합니다. 그래서 우리는 그것을 시퀀스에 넣습니다.

*a, = [1]                            # a = [1]

다음과 같습니다.

(*a,) = (1,)

마지막으로,이 혼란의 공통점은 다음 (1)과 동일합니다 1- 당신은 산술 문에서 튜플을 구분하기 위해 쉼표가 필요합니다.

*a, = (1)                            # ERROR -- 'int' object is not 

이제 중첩을 위해. 실제로이 예제는 "NESTED"섹션에 없습니다. 아마도 당신은 그것이 중첩되었다는 것을 몰랐습니까?

(a,b), *c = 'XY', 2, 3               # a = 'X', b = 'Y', c = [2,3]

된다

((a, b), *c) = (('X', 'Y'), 2, 3)

최상위 튜플의 첫 번째 값이 할당되고, 예상대로 최상위 수준 튜플 ( 23) 의 나머지 값 이 할당됩니다 c.

(a,b),c = 1,2,3                      # ERROR -- too many values to unpack
*(a,b), c = 1,2,3                    # a = 1, b = 2, c = 3

위의 첫 번째 줄에서 오류가 발생하는 이유를 이미 설명했습니다. 두 번째 줄은 어리석지 만 작동하는 이유는 다음과 같습니다.

(*(a, b), c) = (1, 2, 3)

앞서 설명했듯이 우리는 끝에서 일합니다. 3에 할당 된 c다음 나머지 값은 *선행 변수 ( 이 경우)에 할당됩니다 (a, b). 그래서 그것은 (a, b) = (1, 2)올바른 수의 요소가 있기 때문에 작동하는 것과 동일합니다 . 이것이 작업 코드에 나타나는 이유를 생각할 수 없습니다. 비슷하게,

*(a, *b), c = 'this'                 # a = 't', b = ['h', 'i'], c = 's'

된다

(*(a, *b), c) = ('t', 'h', 'i', 's')

이 ( 's'가)에 지정 c되고 ('t', 'h', 'i')에 지정됩니다 (a, *b). 단부에서 다시 작업하기 't'에 할당 a('h', 'i')리스트로서 b에 할당된다. 이것은 작업 코드에서 절대 나타나지 않아야하는 또 다른 어리석은 예입니다.


24
OP는 긴 목록 예제를 제공했기 때문에 긴 설명 목록을 제공하는 것이 적합합니다.
John Y

7

파이썬 2 튜플을 풀면 꽤 간단합니다. 왼쪽의 각 이름은 전체 시퀀스 또는 오른쪽 시퀀스의 단일 항목에 해당합니다. 이름이 시퀀스의 단일 항목에 해당하는 경우 모든 항목을 포함 할 수있는 충분한 이름이 있어야합니다.

그러나 확장 된 압축 풀기는 매우 강력하기 때문에 확실히 혼란 스러울 수 있습니다. 현실은 당신이 제공 한 마지막 10 개 이상의 유효한 예제를 절대 수행해서는 안된다는 것입니다 dict.

분명히 새로운 구문은 남용 될 수 있습니다. 귀하의 질문에 대한 대답은 그런 표현을 읽을 필요가 없다는 것입니다.

임의로 복잡한 표현을 쓸 수 있다고해서 그렇게해야한다는 의미는 아닙니다. 당신은 같은 코드를 작성할 수 map(map, iterable_of_transformations, map(map, iterable_of_transformations, iterable_of_iterables_of_iterables))있지만 그렇지 않습니다 .


참고 : 여러 수준이 더 복잡한 것을 제외하고는 이와 같은 코드를 작성했습니다. 연습용으로 만 의도되었으며 3 개월 후에는 나에게 의미가 없고 다른 사람이 이해할 수 없다는 것을 충분히 알고 있었습니다. 내가 옳다는 것을 기억한다면, 그것은 폴리곤 테스트의 포인트를 구현하고, 좌표 변환을 수행하고, 일부 SVG, HTML 및 JavaScript를 제작했습니다.
agf

3

귀하의 코드가 다른 형식을 사용하여 오해의 소지가 있다고 생각합니다.

연산자 우선 순위에 대한 질문을 피하기 위해 표현식에 추가 대괄호를 사용하는 것과 같습니다. 나는 당신의 코드를 읽기 쉽게 만들기 위해 항상 좋은 투자입니다.

나는 스왑과 같은 간단한 작업에만 풀기를 사용하는 것을 선호합니다.

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