[python] x, y = zip (* zip (a, b))이 파이썬에서 작동하는 이유는 무엇입니까?

좋아요 저는 Python의 zip()기능을 좋아 합니다. 항상 사용하십시오. 훌륭합니다. 가끔씩 나는 zip()“나는 그 방법을 알고 있었다”고 생각하고, 구글 파이썬 압축을 풀고, *튜플의 압축 목록을 압축 해제하기 위해이 마법 을 사용한다는 것을 기억한다 . 이렇게 :

x = [1,2,3]
y = [4,5,6]
zipped = zip(x,y)
unzipped_x, unzipped_y = zip(*zipped)
unzipped_x
    Out[30]: (1, 2, 3)
unzipped_y
    Out[31]: (4, 5, 6)

도대체 무슨 일이 일어나고 있습니까? 마법의 별표는 무엇을하고 있습니까? 다른 곳에 적용 할 수 있으며 Python의 다른 놀라운 기능이 신비스럽고 Google에 어려운 점은 무엇입니까?



답변

Python의 별표는 Python 자습서의 Unpacking Argument Lists 아래에 설명되어 있습니다.


답변

별표는 수행합니다 apply(Lisp 및 Scheme에서 알려짐). 기본적으로 목록을 가져 와서 해당 목록의 내용을 인수로 사용하여 함수를 호출합니다.


답변

다중 인수에도 유용합니다.

def foo(*args):
  print args

foo(1, 2, 3) # (1, 2, 3)

# also legal
t = (1, 2, 3)
foo(*t) # (1, 2, 3)

그리고 키워드 인수와 사전에 이중 별표를 사용할 수 있습니다.

def foo(**kwargs):
   print kwargs

foo(a=1, b=2) # {'a': 1, 'b': 2}

# also legal
d = {"a": 1, "b": 2}
foo(**d) # {'a': 1, 'b': 2}

물론 다음을 결합 할 수 있습니다.

def foo(*args, **kwargs):
   print args, kwargs

foo(1, 2, a=3, b=4) # (1, 2) {'a': 3, 'b': 4}

꽤 깔끔하고 유용한 것들.


답변

항상 작동하지는 않습니다.

>>> x = []
>>> y = []
>>> zipped = zip(x, y)
>>> unzipped_x, unzipped_y = zip(*zipped)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: need more than 0 values to unpack

이런! 나는 그것이 작동하도록 겁을 주려면 두개골이 필요하다고 생각합니다.

>>> unzipped_x, unzipped_y = zip(*zipped) or ([], [])
>>> unzipped_x
[]
>>> unzipped_y
[]

python3에서 나는 당신이 필요하다고 생각합니다.

>>> unzipped_x, unzipped_y = tuple(zip(*zipped)) or ([], [])

zip은 이제 False-y가 아닌 생성기 함수를 반환하기 때문입니다.


답변

저는 Python을 처음 접했기 때문에 최근에 저를 엉망으로 만들었지 만 예제가 어떻게 제시되고 무엇을 강조했는지에 대해 더 많은 일을해야했습니다.

zip 예제를 이해하는 데 문제를 준 것은 zip 호출 반환 값 처리의 비대칭이었습니다. 즉, zip이 처음 호출되면 반환 값이 단일 변수에 할당되어 목록 참조 (생성 된 튜플 목록 포함)가 생성됩니다. 두 번째 호출에서는 목록 (또는 컬렉션?) 반환 값을 여러 변수 참조에 자동으로 압축 해제하는 Python의 기능을 활용하며 각 참조는 개별 튜플입니다. 누군가 파이썬에서 작동하는 방식에 익숙하지 않으면 실제로 일어나는 일에 대해 길을 잃기 쉽습니다.

>>> x = [1, 2, 3]
>>> y = "abc"
>>> zipped = zip(x, y)
>>> zipped
[(1, 'a'), (2, 'b'), (3, 'c')]
>>> z1, z2, z3 = zip(x, y)
>>> z1
(1, 'a')
>>> z2
(2, 'b')
>>> z3
(3, 'c')
>>> rezipped = zip(*zipped)
>>> rezipped
[(1, 2, 3), ('a', 'b', 'c')]
>>> rezipped2 = zip(z1, z2, z3)
>>> rezipped == rezipped2
True


답변

@bcherry의 답변에 대한 부록 :

>>> def f(a2,a1):
...  print a2, a1
... 
>>> d = {'a1': 111, 'a2': 222}
>>> f(**d)
222 111

따라서 키워드 인수 ( 이 엄격한 의미에서 )뿐만 아니라 명명 된 인수 (일명 위치 인수)에서도 작동합니다.


답변

(x, y) == tuple(zip(*zip(x,y))) 다음 두 문장이 참인 경우에만 참입니다.

  • xy 같은 길이가
  • xy튜플은

진행 상황을 이해하는 한 가지 좋은 방법은 각 단계에서 인쇄하는 것입니다.

x = [1, 2, 3]
y = ["a", "b", "c", "d"]

print("1) x, y = ", x, y)
print("2) zip(x, y) = ", list(zip(x, y)))
print("3) *zip(x, y) = ", *zip(x, y))
print("4) zip(*zip(x,y)) = ", list(zip(*zip(x,y))))

출력되는 내용 :

1) x, y =            [1, 2, 3] ['a', 'b', 'c', 'd']
2) zip(x, y) =       [(1, 'a'), (2, 'b'), (3, 'c')]
3) *zip(x, y) =       (1, 'a')  (2, 'b')  (3, 'c')
4) zip(*zip(x,y)) =  [(1, 2, 3), ('a', 'b', 'c')]

기본적으로 다음과 같은 일이 발생합니다.

  1. x및 항목y 해당 인덱스에 따라 쌍을 이룹니다.
  2. 쌍은 3 개의 다른 개체 (튜플)로 압축 해제됩니다.
  3. 쌍은 zip으로 전달되며, 이는 다시 색인을 기반으로 모든 항목을 쌍으로 만듭니다.
    • 모든 입력의 첫 번째 항목이 쌍을 이룹니다. (1, 2, 3)
    • 모든 입력의 두 번째 항목이 쌍을 이룹니다. ('a', 'b', 'c')

이제이 (x, y) == tuple(zip(*zip(x,y)))경우 왜 거짓 인지 이해할 수 있습니다 .

  • 이후 y이상이며 x, 최초의 우편 작업이에서 추가 항목을 제거y (이 짝되지 않을 수 있기 때문에), 이러한 변화는 분명 둘째을 압축 작업에 repercuted한다
  • 유형이 다르지만 처음에는 두 개의 목록이 있었지만 이제는 zip목록이 아닌 튜플의 쌍 항목 처럼 두 개의 튜플 이 있습니다.

어떻게 zip작동 하는지 100 % 확실하지 않다면 여기에이 질문에 대한 답을 썼습니다. Unzipping 및 * 연산자