code

zip (* [iter (s)] * n)은 파이썬에서 어떻게 작동합니까?

codestyles 2020. 8. 30. 08:39
반응형

zip (* [iter (s)] * n)은 파이썬에서 어떻게 작동합니까?


s = [1,2,3,4,5,6,7,8,9]
n = 3

zip(*[iter(s)]*n) # returns [(1,2,3),(4,5,6),(7,8,9)]

어떻게 zip(*[iter(s)]*n)작동합니까? 좀 더 자세한 코드로 작성했다면 어떤 모습일까요?


iter()시퀀스에 대한 반복자입니다. 수량을 [x] * n포함하는 목록 , 즉 각 요소가있는 길이 목록을 생성합니다 . 함수 호출을 위해 시퀀스를 인수로 압축 해제합니다. 따라서 동일한 반복자를에 3 번 전달하고 매번 반복기에서 항목을 가져옵니다.nxnx*argzip()

x = iter([1,2,3,4,5,6,7,8,9])
print zip(x, x, x)

다른 훌륭한 답변과 주석은 인수 압축 해제zip () 의 역할을 잘 설명합니다 .

으로 이그나시오ujukatzel 말하자면, 당신은에 전달 zip()같은 반복자 세 참조와 zip()주문의 반복자에 대한 각 참조에 정수-의 3 튜플한다 :

1,2,3,4,5,6,7,8,9  1,2,3,4,5,6,7,8,9  1,2,3,4,5,6,7,8,9
^                    ^                    ^            
      ^                    ^                    ^
            ^                    ^                    ^

그리고 더 자세한 코드 샘플을 요청했기 때문에 :

chunk_size = 3
L = [1,2,3,4,5,6,7,8,9]

# iterate over L in steps of 3
for start in range(0,len(L),chunk_size): # xrange() in 2.x; range() in 3.x
    end = start + chunk_size
    print L[start:end] # three-item chunks

start의 값을 따릅니다 end.

[0:3) #[1,2,3]
[3:6) #[4,5,6]
[6:9) #[7,8,9]

FWIW, 다음 map()과 같은 초기 인수를 사용 하여 동일한 결과를 얻을 수 있습니다 None.

>>> map(None,*[iter(s)]*3)
[(1, 2, 3), (4, 5, 6), (7, 8, 9)]

에 대한 자세한 내용 zip()map(): http://muffinresearch.co.uk/archives/2007/10/16/python-transposing-lists-with-map-and-zip/


모든 답변에서 놓친 것 (반복자에 익숙한 사람들에게는 분명 할 것임)이 있지만 다른 사람들에게는 그렇게 분명하지 않은 것은 다음과 같습니다.

동일한 이터레이터가 있기 때문에 소비되고 나머지 요소는 zip에서 사용됩니다. 그래서 우리가 단순히 목록을 사용하고 iter를 사용하지 않는다면.

l = range(9)
zip(*([l]*3)) # note: not an iter here, the lists are not emptied as we iterate 
# output 
[(0, 0, 0), (1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4), (5, 5, 5), (6, 6, 6), (7, 7, 7), (8, 8, 8)]

반복자를 사용하여 값을 팝하고 사용 가능한 상태 만 유지하므로 zip의 경우 0이 소비되면 1을 사용할 수 있고 2를 계속 사용할 수 있습니다. 매우 미묘하지만 아주 영리합니다 !!!


iter(s) s에 대한 반복자를 반환합니다.

[iter(s)]*n s에 대해 동일한 반복기의 n 배 목록을 만듭니다.

따라서를 수행 할 때 zip(*[iter(s)]*n)목록에서 세 개의 반복자 모두에서 항목을 순서대로 추출합니다. 모든 이터레이터는 동일한 객체이기 때문에 목록을 n.


One word of advice for using zip this way. It will truncate your list if it's length is not evenly divisible. To work around this you could either use itertools.izip_longest if you can accept fill values. Or you could use something like this:

def n_split(iterable, n):
    num_extra = len(iterable) % n
    zipped = zip(*[iter(iterable)] * n)
    return zipped if not num_extra else zipped + [iterable[-num_extra:], ]

Usage:

for ints in n_split(range(1,12), 3):
    print ', '.join([str(i) for i in ints])

Prints:

1, 2, 3
4, 5, 6
7, 8, 9
10, 11

It is probably easier to see what is happening in python interpreter or ipython with n = 2:

In [35]: [iter("ABCDEFGH")]*2
Out[35]: [<iterator at 0x6be4128>, <iterator at 0x6be4128>]

So, we have a list of two iterators which are pointing to the same iterator object. Remember that iter on a object returns an iterator object and in this scenario, it is the same iterator twice due to the *2 python syntactic sugar. Iterators also run only once.

Further, zip takes any number of iterables (sequences are iterables) and creates tuple from i'th element of each of the input sequences. Since both iterators are identical in our case, zip moves the same iterator twice for each 2-element tuple of output.

In [41]: help(zip)
Help on built-in function zip in module __builtin__:

zip(...)
    zip(seq1 [, seq2 [...]]) -> [(seq1[0], seq2[0] ...), (...)]

    Return a list of tuples, where each tuple contains the i-th element
    from each of the argument sequences.  The returned list is truncated
    in length to the length of the shortest argument sequence.

The unpacking (*) operator ensures that the iterators run to exhaustion which in this case is until there is not enough input to create a 2-element tuple.

This can be extended to any value of n and zip(*[iter(s)]*n) works as described.

참고URL : https://stackoverflow.com/questions/2233204/how-does-zipitersn-work-in-python

반응형