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)
작동합니까? 좀 더 자세한 코드로 작성했다면 어떤 모습일까요?
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 번 전달하고 매번 반복기에서 항목을 가져옵니다.n
x
n
x
*arg
zip()
x = iter([1,2,3,4,5,6,7,8,9])
print zip(x, x, x)
yield
s (= return
s) 할 때이 항목을 "소비 된"것으로 상상할 수 있습니다. 따라서 다음에 반복자가 호출되면 다음 "사용되지 않은"항목이 생성됩니다.
다른 훌륭한 답변과 주석은 인수 압축 해제 및 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
.
이런 식으로 zip을 사용하는 것에 대한 조언 한마디. 길이가 균등하게 나눌 수 없으면 목록이 잘립니다. 이 문제를 해결하려면 채우기 값을 허용 할 수있는 경우 itertools.izip_longest 를 사용할 수 있습니다. 또는 다음과 같이 사용할 수 있습니다.
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:], ]
용법:
for ints in n_split(range(1,12), 3):
print ', '.join([str(i) for i in ints])
인쇄물:
1, 2, 3
4, 5, 6
7, 8, 9
10, 11
itertools
레시피에 문서화되어 있습니다 : docs.python.org/2/library/itertools.html#recipes grouper
. 바퀴 재발견 할 필요가 없습니다
파이썬 인터프리터에서 어떤 일이 일어나고 있는지 보는 것이 더 쉬울 것 ipython
입니다 n = 2
.
In [35]: [iter("ABCDEFGH")]*2
Out[35]: [<iterator at 0x6be4128>, <iterator at 0x6be4128>]
따라서 동일한 반복기 객체를 가리키는 두 개의 반복기 목록이 있습니다. iter
객체에서 반복자 객체를 반환하고이 시나리오에서는 *2
파이썬 구문 설탕 으로 인해 동일한 반복자가 두 번 임을 기억하십시오 . 반복기는 한 번만 실행됩니다.
또한, zip
반복 가능한 개수 ( 시퀀스 는 반복 가능 )를 취하고 각 입력 시퀀스의 i 번째 요소에서 튜플을 생성합니다. 우리의 경우 두 반복자가 동일하기 때문에 zip은 출력의 각 2 요소 튜플에 대해 동일한 반복기를 두 번 이동합니다.
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.
풀고 ( *
) 연산자 보장 반복자이 경우 2 소자 터플을 생성하기에 충분한 입력이 없을 때까지이다 소진 실행할 것이다.
이것은의 값으로 확장 할 수 있습니다 n
및 zip(*[iter(s)]*n)
설명 된대로 작동합니다.
*
는 객체를 복제하는 데 편리합니다. 스칼라로 시도한 다음 목록으로 시도하십시오. 또한 시도 print(*zip(*[iter("ABCDEFG")]*2))
대 print(*zip(*[iter("ABCDEFG"), iter("ABCDEFG")]))
. 그런 다음 두 명령문에서 실제로 반복기 객체가 무엇인지 확인하기 위해 두 단계를 더 작은 단계로 분해하기 시작합니다.