3

は、真の「タプルの内包表記は」存在しないことが述べられています。代わりに、私たちの現在のオプションは、ジェネレータ式を使用して、タプルのコンストラクタに結果ジェネレータオブジェクトを渡すことです。また「タプル内包」とスタースプラット/アンパック演算子*

tuple(thing for thing in things) 

、我々はリストの内包表記を使用してリストを作成し、タプルのコンストラクタにリストを渡すことができます。

最後
tuple([thing for thing in things]) 

と受け入れ答えのそれとは反対に、a more recent answerはタプルの内包表記が実際に次の構文を使用して(Pythonの3.5以降)のものであることを述べた:

*(thing for thing in things), 
  • 私にとっては、第2の例も、ジェネレータオブジェクトが最初に作成される例であるようです。これは正しいです?

  • 舞台裏でこれらの表現に違いはありますか?パフォーマンス面では?私は第1と第3がレイテンシの問題を抱えているのに対し、第2と第3はメモリの問題があると考えています(リンクされたコメントで議論されているように)。

  • 最初のものと最後のものを比較すると、どれが1つのピジョンが多いのですか?

更新:予想通り

、リストの内包が実際にはるかに高速です。私はなぜ最初のものが第3のものよりも速いのか理解していない。何かご意見は?私に

>>> from timeit import timeit 

>>> a = 'tuple(i for i in range(10000))' 
>>> b = 'tuple([i for i in range(10000)])' 
>>> c = '*(i for i in range(10000)),' 

>>> print('A:', timeit(a, number=1000000)) 
>>> print('B:', timeit(b, number=1000000)) 
>>> print('C:', timeit(c, number=1000000)) 

A: 438.98362647295824 
B: 271.7554752581845 
C: 455.59842588083677 
+0

パフォーマンスについてお尋ねします。それらをテストしてください。 ipythonで '%timeit'を試してください。あなたの特定のマシンでどれが良いかを調べてください。 –

+0

リスト内包の 'x for y in z'はジェネレータのように見えるかもしれませんが、そうではありません。内部の仕組みは異なっています。例えば。 'x'部分で生成された' StopIteration'はジェネレータを停止しますが、リストの理解からバブルします。 – schwobaseggl

+2

タプルは一般的に、静的に知られている可能性のある異種のアイテムのセット(これは、例えば、上に配置することができます)を表現するために使用され、各位置に関連する意味的意味があるため、どちらも非常にpythonicではないと思います。リストは、反復のような操作が意味を成す、不確定で均質な多数に適しています。それはちょうど私の意見です。 –

答えて

1

第二の例はまた、発電機 オブジェクトが最初に作成されたものであるように、それはそうです。これは正しいです?

はい、あなたが正しいなら、CPythonのバイトコードをチェックアウト:

>>> import dis 
>>> dis.dis("*(thing for thing in thing),") 
    1   0 LOAD_CONST    0 (<code object <genexpr> at 0x7f56e9347ed0, file "<dis>", line 1>) 
       2 LOAD_CONST    1 ('<genexpr>') 
       4 MAKE_FUNCTION   0 
       6 LOAD_NAME    0 (thing) 
       8 GET_ITER 
      10 CALL_FUNCTION   1 
      12 BUILD_TUPLE_UNPACK  1 
      14 POP_TOP 
      16 LOAD_CONST    2 (None) 
      18 RETURN_VALUE 

は が舞台裏で何の点では、これらの式の間のいずれかの違いはありますか?パフォーマンス面では?私は最初に と仮定し、3番目にレイテンシの問題があり、2番目のメモリには の問題がある可能性があります(リンクされたコメントで説明しています)。

>>> from timeit import timeit 
>>> def f1(): tuple(thing for thing in range(100000)) 
... 
>>> def f2(): *(thing for thing in range(100000)), 
... 
>>> timeit(lambda: f1(), number=100) 
0.5535585517063737 
>>> timeit(lambda: f2(), number=100) 
0.6043887557461858 

最初のものと最後を比較すると、1は次のとおりです。

私のタイミングは最初の1は、開梱はtuple()コールよりもBUILD_TUPLE_UNPACKを経由して、より高価であると思われるので、少し速くであることを示唆していますより多くのpythonic?

私のはるかに読みやすく、さまざまなPythonバージョンでも動作します。

関連する問題