Programing

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

lottogame 2020. 10. 20. 07:13
반응형

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))) is true if and only if the two following statements are true:

  • x and y have the same length
  • x and y are tuples

One good way to understand what's going on is to print at each step:

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

Which outputs:

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

Basically this is what happens:

  1. Items from x and y are paired according to their respective indexes.
  2. Pairs are unpacked to 3 different objects (tuples)
  3. Pairs are passed to zip, which will again, pair every items based on indexes:
    • first items from all inputs are paired: (1, 2, 3)
    • second items from all inputs are paired: ('a', 'b', 'c')

Now you can understand why (x, y) == tuple(zip(*zip(x,y))) is false in this case:

  • since y is longer than x, the first zip operation removed the extra item from y (as it couldn't be paired), this change is obviously repercuted on the second zipping operation
  • types differ, at start we had two lists, now we have two tuples as zip does pair items in tuples and not in lists

If you're not 100% certain to understand how zip work, I wrote an answer to this question here: Unzipping and the * operator

참고URL : https://stackoverflow.com/questions/2511300/why-does-x-y-zipzipa-b-work-in-python

반응형