2016-06-25 15 views
4

x = [1,2,3,4]とすると、i = iter(x)からイテレータを取得できます。Pythonイテレータとジップ

このイテレータでは、zip関数を使用して2つの項目を含むタプルを作成できます。

>>> i = iter(x) 
>>> zip(i,i) 
[(1, 2), (3, 4)] 

この構文を使用しても同じ結果が得られます。

>>> zip(*[i] * 2) 
[(1, 2), (3, 4)] 

これはどのように機能しますか? zip(i,i)zip(*[i] * 2)のイテレータはどのように機能しますか?

+2

'[I] * 2 – falsetru

答えて

7

イテレータはアイテムのストリームのようなものです。ストリームのアイテムは一度に1つしか見ることができず、最初の要素にしかアクセスできません。ストリーム内の何かを見るには、ストリームからそれを削除する必要があります。ストリームの上から何かを取ると、ストリームから消えてしまいます。

zip(i, i)に電話すると、zipは最初に最初のストリームを見てアイテムを取り出します。次に、それは第2のストリームを見て(これはと同じストリーム最初のストリームと同じです)、アイテムを取り出します。次に、ストリームに何も残らないまで、これらの2つのアイテムからタプルを作り、これを何度も繰り返します。

zip関数を純粋なpythonで書くのは簡単でしょうか(簡略化のために2つの引数しかありません)。それはのようになります。

def zip(a, b): 
    out = [] 
    try: 
     while True: 
      item1 = next(a) 
      item2 = next(b) 
      out.append((item1, item2)) 
    except StopIteration: 
     return out 

は今、あなたはabが同じオブジェクトある場所について話している場合を想像してみてください。この場合、イテレータ(例ではi)でnextを2回呼び出すだけで、最初の2つのアイテムを順番にiから取り出し、それらをタプルにパックします。

zip(i, i)がどのように動作するのかわかると、zip(*([i] * 2))はそれほど難しくありません。 ...

[i] * 2 

を内側から式を読み出すだけの要素の両方がイテレータiへの参照である(長さ2の)新しいリストを作成することができます。したがって、zip(*[i, i])と同じことです(何度も何度も何度も何度も何度も繰り返したい場合は、書くほうが便利です)。 *アンパックはPythonの共通の慣用句であり、詳細はthe python tutorialにあります。それの要点は、Pythonはiterableを取り、iterableの各項目が関数の個別の位置引数であるかのように "展開"することです。だから、:

zip(i, i) 

そして今、ボブの私たちの叔父:

zip(*[i, i]) 

は同じことを行います。このディスカッションが始まったのはzip(i, i)なので、今度は一周しました。

この例のコードは、前述の2つの引数を受け入れるだけではありません。例えば、zipは、おそらくそれはどんなイテラブル(だけでなく、イテレータ)のために働くように入力引数にiterを呼び出すために起こっているが、これは全体のポイントを取得するのに十分でなければなりません...

+0

['zip'はpython2でリストを返し、python3でイテレータを返します]({{i、i} http://www.diveintopython3.net/porting-code-to-python-3-with-2to3.html#zip)。 –

0

イテレータからアイテムを取得するたびに、「巻き戻し」ではなくその場所にとどまります。したがって、zip(i, i)iから最初の項目を取得し、次にiから2番目の項目を取得し、tupleとして返します。イテレータが使い果たされるまで、使用可能なペアごとにこれを続けます。

zip(*[i]*2)2によってiを乗じて[i, i]listを作成し、その後、実際に、最初のスニペットと同じ結果を生成する、zipに二つの引数iiを送信する、左端の*とそれをアンパック。