Python (2.7) でこれまで言及されたことのない興味深いことが見つかりました。
これ:
a = []
a += "a"
動作し、結果は次のとおりです。
>>> a
>>> ["a"]
しかし
a = []
a = a + "a"
与える
>>> TypeError: can only concatenate list (not "str") to list
誰かが理由を説明できますか?回答ありがとうございます。
+
Python は演算子と演算子を区別し+=
、これらに個別のフックを提供します。__add__
と__iadd__
。このlist()
型は、後者に対して異なる実装を提供するだけです。
リストがこれらを別々に実装する方が効率的です。__add__
は完全に新しいリストを返す必要がありますが、__iadd__
拡張してから返すことができself
ますself
。
C コードで__iadd__
は、 によって実装されlist_inplace_concat()
ます。これは単に を呼び出すlistextend()
か、Python コードでは を呼び出します[].extend()
。後者は、設計上、任意のシーケンスを取ります。
__add__
一方、C で によって表されるメソッドは、おそらく効率のために、入力としてlist_concat
a のみを受け取ります。list
内部 C 配列を直接ループして、アイテムを新しいリストにコピーできます。
結論として、__iadd__
任意のシーケンスを受け入れる理由は、PEP 203 (Augmented Add 提案) が実装されたとき、リストについては.extend()
メソッドを再利用するのが最も簡単だったからです。
a
がリストの場合、 もリストの場合にのみ機能a + x
しますが、 iterable の場合は機能します。x
a += x
x
以下はそれを理解するのに役立つかもしれません:
In [4]: a = []
In [5]: a += "abc"
In [6]: a
Out[6]: ['a', 'b', 'c']
重要なのは、"a"
と"abc"
が反復可能であることです。これにより、 の右側で使用できるようになります+=
。
+
後者では両方のオペランドが同じ型である必要があるため、これは機能しません(マニュアルを参照)。
を使用して同じことを記述するには+
、イテラブルを展開する必要があります。
In [7]: a = []
In [8]: a = a + list("abc")
In [9]: a
Out[9]: ['a', 'b', 'c']
つまり、リストに適用される場合+=
よりも一般的です。+