Pythonのリストにおけるappend()メソッドとextend()メソッドは、要素を追加するために使用されますが、その方法は根本的に異なります。
append(obj)は1つの要素(任意のオブジェクト、リストも含む)を元のリストの末尾に追加します。extend(iterable)はイテラブルオブジェクトのすべての要素を1つずつ追加します(追加時に「展開」されるような形です)。例:
lst = [1, 2, 3] lst.append([4, 5]) # 結果: [1, 2, 3, [4, 5]] lst = [1, 2, 3] lst.extend([4, 5]) # 結果: [1, 2, 3, 4, 5]
このような違いは、「フラットな」リストを期待しているときに入れ子のリストを受け取ってしまうという論理的なエラーを引き起こす原因になりがちです。
list1 = [1, 2]; list2 = [3, 4]; list1.append(list2)を実行したらどうなりますか?list1はどのようになりますか?list1.extend(list2)との違いは何ですか?
回答:
list1.append(list2)の後の結果: [1, 2, [3, 4]] — 2番目のリストが1つの要素(入れ子のリスト)として追加されます。list1.extend(list2)の後の結果: [1, 2, 3, 4] — 2番目のリストの要素が「展開」されて、個別の要素として追加されます。エピソード
開発者は、複数のファイルからのパース結果を結合する際に
output.append(parsed_lines)を実行しました。結果として、長いフラットなリストの代わりにリストのリスト(各ファイルごとに1つの要素)を得てしまい、その後の処理が壊れました。特に、行のシーケンスを期待する関数は、入力データでエラーを出すようになりました。
エピソード
プロジェクトでは、文字列「foo」を追加するためにextendが使用されていました(つまり、文字列がイテラブルとして扱われていました)。これにより、文字列の文字がリストの個別の要素になってしまった:
['f', 'o', 'o']になり、欲しかった「foo」ではなくなりました。
エピソード
JSONにデータをシリアライズする際に、append/extendがサイクル内で違いを理解せずに適用されました。結果として、スキーマを破る構造が生成され、一部のマイクロサービスがバリデーション段階で落ちたり、正しく動作しなくなった。