[Tips]Pythonのappend・extend以外でListへ要素追加する方法

2019.11.22

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

データアナリティクス事業本部@札幌の佐藤です。

Listへの要素追加は append()extend() 以外にもあるはご存じですか?
今回はTip的な情報となりますが append()extend() 以外の実装について記載したいと思います。

まずListのインプレース演算子を確認

まず dir() でListで何が定義されているかを見てみます。

>>> dir(list)
['__add__',
 '__class__',
 '__contains__',
 '__delattr__',
 '__delitem__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__gt__',
 '__hash__',
 '__iadd__',
 '__imul__',
 '__init__',
 '__init_subclass__',
 '__iter__',
 '__le__',
 '__len__',
 '__lt__',
 '__mul__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__reversed__',
 '__rmul__',
 '__setattr__',
 '__setitem__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 'append',
 'clear',
 'copy',
 'count',
 'extend',
 'index',
 'insert',
 'pop',
 'remove',
 'reverse',
 'sort']

このなかに、 __iadd__ がありますよね。
今回はこいつの話です。

多くの演算に「インプレース」版があります。 以下の関数はそうした演算子の通常の文法に比べてより素朴な呼び出し方を提供します。たとえば、 文 x += y は x = operator.iadd(x, y) と等価です。別の言い方をすると、 z = operator.iadd(x, y) は複合文 z = x; z += y と等価です。
ref:インプレース (in-place) 演算子

つまりListに対して a += b のような書き方ができるということになります。

a += bの記述を試してみる

a += b の記述を試してみたいと思います。

まず通常は要素を追加する場合は、このパターンですね。

>>> s4_26gene = ["虹野ゆめ", "香澄真昼", "早乙女あこ"]
>>> s4_26gene.append("二階堂ゆず")
>>> s4_26gene
['虹野ゆめ', '香澄真昼', '早乙女あこ', '二階堂ゆず']

では同じような感じで a += b で記述してみます。

>>> s4_26gene = ["虹野ゆめ", "香澄真昼", "早乙女あこ"]
>>> s4_26gene += "二階堂ゆず"
>>> s4_26gene
['虹野ゆめ', '香澄真昼', '早乙女あこ', '二', '階', '堂', 'ゆ', 'ず']

はい、全然だめですね。

これは書き方が悪いです。

例えばこのパターンはエラーになります。

>>> example = [1, 2]
>>> example += 3
>>> example = [1, 2]
TypeError: 'int' object is not iterable

このエラーメッセージの通り、渡す値はイテラブルである必要があります。
文字列はイテラブルのため渡すことができますが、シーケンシャルに処理ができる、つまり1ワードではなく1文字ずつ処理されてしまいます。
(逆に言うと渡す値が1文字であれば上記実装でOKです)

そのため、追加するときはリスト同士の結合のような感じで実装してあげる必要があります。

>>> s4_26gene = ["虹野ゆめ", "香澄真昼", "早乙女あこ"]
>>> s4_26gene += ["二階堂ゆず"]
>>> s4_26gene
['虹野ゆめ', '香澄真昼', '早乙女あこ', '二階堂ゆず']

これを見たらわかると思いますが、 extend() と同等ですね。

>>> s4_26gene = ["虹野ゆめ", "香澄真昼", "早乙女あこ"]
>>> s4_26gene.extend(["二階堂ゆず"])
>>> s4_26gene
['虹野ゆめ', '香澄真昼', '早乙女あこ', '二階堂ゆず']

最後に

extend() と同等とはいえ、こういう書き方もできるんだなという感じでした。