2016-08-21 5 views
11

私はインタプリタを驚いていて、わからないものを見つけました。リストとして1つの要素としてタプルを作成し、そのリストを更新しようとすると、何か変なことが起こります。たとえば、私が実行したときに、この:タプル内のリストを更新する

tup = (1,2,3,[4,5]) 
tup[3] += [6] 

私が手:

私は期待まさにある
TypeError: 'tuple' object does not support item assignment 

。私は再びタプルを参照する場合しかし、その後、私が手:だからリストは実際にはPythonが例外をスローしたにもかかわらず、更新された

>>> tup 
(1, 2, 3, [4, 5, 6]) 

。それはどのように機能するのですか?私は実際にこのようなことをしたいシナリオを想像することはできませんが、何が起こっているのかを理解したいと思います。ありがとうございました。

答えて

27

実際にはPython docsに記載されています。

EDIT:これはより完全な答えです。

  1. 我々は+=を使用し、Pythonは、その後の項目の割り当てに戻り値を使用して、項目に__iadd__マジックメソッドを呼び出します。
  2. リストの場合、__iadd__は、リストでextendを呼び出してからリストを返すのと同じです。我々はtup[3] += [6]を呼び出すときに
  3. したがって、それは同等です:

    result = tup[3].__iadd__([6]) 
    tup[3] = result 
    
  4. #2から、我々はこれを決定することができますに相当します。最初の行はextendを呼び出すことに成功した

    result = tup[3].extend([6]) 
    tup[3] = result 
    
  5. リストは変更可能であるため、更新されます。ただし、タプルは不変であり、エラーをスローするため、後続の代入は失敗します。
+2

私は、拡張が単に 'tup [3] .__ iadd __([6])ではな​​いという理由で答えが得られると思います。 'tup [3] = tup [3] .__ iadd __([6])'です。 'list .__ iadd__'が突然変異しているのと同じオブジェクトを返すだけで便利です。 – zondo

+0

ドキュメントへのリンクありがとうございます!それは大きな助けです。 –

+0

ありがとう、私はドキュメントでこれをキャッチしませんでした。だから、私はちょうどtup [3] .__ iadd __([6])を実行しているので、リストが更新されています。だから私はそれが失敗したという例外を出しますが、その時点ですでにリストを更新していますか? –

関連する問題