2017-01-17 1 views
2

タプルはPythonでは非可変データ型なので、タプルの包含は問題ではありません。なぜ、角括弧の代わりに円括弧でリスト内包がうまく動作し、正規のタプルを生成するのですか?なぜ新しい要素をTUPLEに追加すると機能するのですか?

タプルではないリストを定義するために丸括弧が使われていると思いました(私はそこに間違っているとは思いません)。

私の理解では、既に定義されているタプルに値を追加しています。タプルを更新することができます。タプルは変更不可能なので、(Pythonで)起こらないと思います。

私には何の誤りもありません、誰かがこれに合理的な説明があることを教えてください。

これは私のコードです:

ignore = (r"^\@define\s") 
x = tuple() 
(x.append(True if re.search(regex, line) else False) for regex in ignore) 
if True in x: 
    print("How is this possible?") 
+4

それは生成者の理解であり、タプルの理解ではありません。これは、リストの理解によって生成された熱心なシーケンスではなく、レイジーシーケンスを生成します。 –

+1

@PaulRooney 'x.append()'を実行していて、 'x'が' tuple() 'として定義されている場合は、必ず' tuple() 'で' append() 'を実行するべきではありません。 。 –

+8

右、ジェネレータ*式*は評価されないので、エラーは発生しません。さて、あなたは、理解の構造の中でミューテータ法を使うことは決してありません。それは機能的な構造と状態の変化を混ぜることです。それは悪い形です。 –

答えて

9

ジェネレータ式を使用しているため、エラーはスローされません。

>>> x = tuple() 
>>> x 
() 
>>> (x.append(i) for i in range(10)) 
<generator object <genexpr> at 0x110bede60> 

ジェネレータは遅れて評価され、ジェネレータは変数に取り込まれていないため、ガベージコレクションだけになります。

>>> g = (x.append(i) for i in range(10)) 
>>> next(g) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 1, in <genexpr> 
AttributeError: 'tuple' object has no attribute 'append' 

発電イテレータを書くための迅速な、クールな方法です。しかし、私は使用に発電を行うときに何が起こるか見てください。 発電表現は基本的に「発電用リスト内包」ですが、yieldを使用して発電機を書き込むことができます。

>>> def my_generator(): 
... yield 1 
... yield 3 
... 
>>> g = my_generator() 
>>> next(g) 
1 
>>> next(g) 
3 
>>> next(g) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
StopIteration 
>>> list(my_generator()) 
[1, 3] 
>>> 

さて、ジェネレータ式についてのクールなことは、あなたがtupleコンストラクタでそれらを組み合わせることができています、任意の反復可能性があり、あなたは貧しい人のタプル理解力を持っています。 、それはまず

>>> x = [] 
>>> [x.append(i) for i in range(10)] 
[None, None, None, None, None, None, None, None, None, None] 
>>> x 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 

です:あなたはこのような決して実行コードする必要があり、余談として

>>> tuple(x for x in range(20)) 
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19) 
>>> 

:*一つのパラメータのみが存在する場合は、関数の引数に括弧をドロップすることができ、注意してくださいそれは全く役に立たないNoneのリストを作成するので無駄です。第二に、それは、機能的な構造、リストの理解、状態の変更(.append)、それは悪い形で混ざっています。 Pythonのプログラマーは、リストの理解にはそうしないことを期待しています。 命令コードのforループを使用してください。

+0

実際の追加ではありませんが、わかりやすくするために、「ジェネレータ表現からのタプルを作成する方法」( 'tuple(gen)')を追加する必要があります。ジェネレータの式とタプルの作成との間の異なる構文を直接比較することができます。 – paul23

+0

私にこれを説明する時間をとってくれてありがとう、そして深い答えをありがとう。 –

4

はあなたのREPLに沿って自宅で従わせるようさんがこのような形で、単純な例を紹介しましょう:

>>> def error(): raise Exception 
... 
>>> (error() for x in range(5)) 
<generator object <genexpr> at 0x7fb1a371f2d0> 

(error() for x in range(5) genexpです - - ジェネレータ式。それが評価されると、要求に応じて遅延生成できるジェネレータオブジェクトが生成されますが、今は何も生成しないように依頼しています。したがって、そこに含まれるコードは実行されていません。これとは対照的に

は、我々はタプルの中に私たちの発電機の出力を展開しようとすると、何が起こるか見てみましょう:

>>> tuple(_) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 1, in <genexpr> 
    File "<stdin>", line 1, in error 
Exception 

ブーム!

+0

実際の追加ではありませんが、わかりやすくするために、「ジェネレータ表現からタプルをインラインで作成する方法」( 'tuple(gen)') – paul23

+0

時間をかけて説明してくれてありがとう、ありがとう。 –

関連する問題