append()
list メソッドとの違いは何extend()
ですか?
20 に答える
append
リストに要素を追加しextend
、最初のリストを別のリスト (または別のイテラブル、必ずしもリストではない) と連結します。
>>> li = ['a', 'b', 'mpilgrim', 'z', 'example']
>>> li
['a', 'b', 'mpilgrim', 'z', 'example']
>>> li.append("new")
>>> li
['a', 'b', 'mpilgrim', 'z', 'example', 'new']
>>> li.append(["new", 2])
>>> li
['a', 'b', 'mpilgrim', 'z', 'example', 'new', ['new', 2]]
>>> li.insert(2, "new")
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', ['new', 2]]
>>> li.extend(["two", "elements"])
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', ['new', 2], 'two', 'elements']
リストメソッドの追加と拡張の違いは何ですか?
append
その引数を単一の要素としてリストの末尾に追加します。リスト自体の長さが 1 つ増えます。extend
リストに各要素を追加し、リストを拡張する引数を反復処理します。リストの長さは、 iterable 引数に含まれる要素の数だけ増加します。
append
このlist.append
メソッドは、リストの末尾にオブジェクトを追加します。
my_list.append(object)
数値、文字列、別のリストなど、オブジェクトが何であれ、リストmy_list
の単一のエントリとして の最後に追加されます。
>>> my_list
['foo', 'bar']
>>> my_list.append('baz')
>>> my_list
['foo', 'bar', 'baz']
したがって、リストはオブジェクトであることに注意してください。リストに別のリストを追加すると、最初のリストはリストの最後にある単一のオブジェクトになります (これは望ましくない場合があります)。
>>> another_list = [1, 2, 3]
>>> my_list.append(another_list)
>>> my_list
['foo', 'bar', 'baz', [1, 2, 3]]
#^^^^^^^^^--- single item at the end of the list.
extend
このlist.extend
メソッドは、イテラブルから要素を追加してリストを拡張します。
my_list.extend(iterable)
したがって、extend を使用すると、イテラブルの各要素がリストに追加されます。例えば:
>>> my_list
['foo', 'bar']
>>> another_list = [1, 2, 3]
>>> my_list.extend(another_list)
>>> my_list
['foo', 'bar', 1, 2, 3]
文字列は反復可能であることを覚えておいてください。そのため、文字列でリストを拡張する場合、文字列を反復処理するときに各文字を追加します (これは望ましくない場合があります)。
>>> my_list.extend('baz')
>>> my_list
['foo', 'bar', 1, 2, 3, 'b', 'a', 'z']
演算子のオーバーロード、__add__
( +
) および__iadd__
( +=
)
には と の両方+
の+=
演算子が定義されていlist
ます。それらは拡張と意味的に似ています。
my_list + another_list
メモリ内に 3 番目のリストを作成するため、その結果を返すことができますが、2 番目の iterable がリストである必要があります。
my_list += another_list
リストをインプレースで変更する (これはインプレース演算子であり、これまで見てきたようにリストは変更可能なオブジェクトです) ため、新しいリストは作成されません。また、2 番目の iterable はあらゆる種類の iterable にできるという点で、extend のように機能します。
混乱しないでください -my_list = my_list + another_list
と同等ではありません+=
- my_list に割り当てられた新しいリストを提供します。
時間の複雑さ
Append は (償却された)一定時間の複雑さ、O(1) を持っています。
Extend には時間計算量 O(k) があります。
複数の呼び出しを反復するとappend
複雑さが増し、extend と同等になります。extend の反復は C で実装されているため、イテラブルからリストに連続する項目を追加する場合は、常に高速になります。
「償却」について-リストオブジェクトの実装ソースから:
/* This over-allocates proportional to the list size, making room
* for additional growth. The over-allocation is mild, but is
* enough to give linear-time amortized behavior over a long
* sequence of appends() in the presence of a poorly-performing
* system realloc().
これは、事前に必要以上に大きなメモリ再割り当ての利点を得ることができることを意味しますが、次の限界再割り当てでさらに大きなものを支払う可能性があります。すべての追加の合計時間は O(n) で線形であり、追加ごとに割り当てられる時間は O(1) になります。
パフォーマンス
append を使用してextend と同じ結果を得ることができるため、何がよりパフォーマンスに優れているのか疑問に思うかもしれません。次の関数は同じことを行います。
def append(alist, iterable):
for item in iterable:
alist.append(item)
def extend(alist, iterable):
alist.extend(iterable)
それでは、それらの時間を計りましょう。
import timeit
>>> min(timeit.repeat(lambda: append([], "abcdefghijklmnopqrstuvwxyz")))
2.867846965789795
>>> min(timeit.repeat(lambda: extend([], "abcdefghijklmnopqrstuvwxyz")))
0.8060121536254883
タイミングに関するコメントへの対応
コメンターは次のように述べています。
完璧な答え、要素を1つだけ追加して比較するタイミングを逃しただけです
意味的に正しいことを行います。iterable 内のすべての要素を追加する場合は、 を使用しますextend
。要素を 1 つだけ追加する場合は、append
.
では、実験を作成して、これが時間内にどのように機能するかを確認しましょう。
def append_one(a_list, element):
a_list.append(element)
def extend_one(a_list, element):
"""creating a new list is semantically the most direct
way to create an iterable to give to extend"""
a_list.extend([element])
import timeit
そして、extend を使用するためだけに iterable を作成するのは (マイナーな) 時間の無駄であることがわかります。
>>> min(timeit.repeat(lambda: append_one([], 0)))
0.2082819009956438
>>> min(timeit.repeat(lambda: extend_one([], 0)))
0.2397019260097295
このことから、追加する要素が1 つextend
しかない場合に使用しても何も得られないことがわかります。
また、これらのタイミングはそれほど重要ではありません。Python では、意味的に正しいことを行うことは、Right Way™ を行うことであるということを指摘するように彼らに示しているだけです。
比較可能な 2 つの操作でタイミングをテストし、あいまいな結果または逆の結果が得られる可能性があります。意味的に正しいことをすることに集中してください。
結論
iterable 内の各要素をリストに追加しようとする場合、のextend
方が意味的に明確であり、 よりもはるかに高速に実行できることがわかります。append
リストに追加する要素が 1 つしかない (イテラブルではない) 場合は、 を使用しますappend
。
append
単一の要素を追加します。extend
要素のリストを追加します。
追加するリストを渡す場合でも、1 つの要素が追加されることに注意してください。
>>> a = [1, 2, 3]
>>> a.append([4, 5, 6])
>>> a
[1, 2, 3, [4, 5, 6]]
次の 2 つのスニペットは意味的に同等です。
for item in iterator:
a_list.append(item)
と
a_list.extend(iterator)
ループが C で実装されているため、後者の方が高速な場合があります。
その場で拡張する代わりに、拡張を返すために「+」を使用できます。
l1=range(10)
l1+[11]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11]
l2=range(10,1,-1)
l1+l2
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2]
インプレース動作についても同様ですが、 &+=
とはわずかに異なります。fromとfromの最大の違いの 1 つは、関数スコープで使用される場合です。このブログ投稿を参照してください。append
extend
+=
append
extend
extend()
イテレータ引数とともに使用できます。ここに例があります。この方法でリストのリストからリストを作成したい:
から
list2d = [[1,2,3],[4,5,6], [7], [8,9]]
あなたが欲しい
>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9]
あなたはそうするために使用するかもしれitertools.chain.from_iterable()
ません。このメソッドの出力は反復子です。その実装は次と同等です
def from_iterable(iterables):
# chain.from_iterable(['ABC', 'DEF']) --> A B C D E F
for it in iterables:
for element in it:
yield element
例に戻ると、次のことができます
import itertools
list2d = [[1,2,3],[4,5,6], [7], [8,9]]
merged = list(itertools.chain.from_iterable(list2d))
そして指名手配リストを取得します。
イテレータ引数で同等extend()
に使用する方法は次のとおりです。
merged = []
merged.extend(itertools.chain.from_iterable(list2d))
print(merged)
>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9]
append() : 基本的に Python で 1 つの要素を追加するために使用されます。
例 1:
>> a = [1, 2, 3, 4]
>> a.append(5)
>> print(a)
>> a = [1, 2, 3, 4, 5]
例 2:
>> a = [1, 2, 3, 4]
>> a.append([5, 6])
>> print(a)
>> a = [1, 2, 3, 4, [5, 6]]
extend() : extend() は、2 つのリストをマージするか、1 つのリストに複数の要素を挿入するために使用されます。
例 1:
>> a = [1, 2, 3, 4]
>> b = [5, 6, 7, 8]
>> a.extend(b)
>> print(a)
>> a = [1, 2, 3, 4, 5, 6, 7, 8]
例 2:
>> a = [1, 2, 3, 4]
>> a.extend([5, 6])
>> print(a)
>> a = [1, 2, 3, 4, 5, 6]
Append は、データ全体を一度に追加します。データ全体が新しく作成されたインデックスに追加されます。一方、extend
はその名前が示すように、現在の配列を拡張します。
例えば
list1 = [123, 456, 678]
list2 = [111, 222]
次のようにappend
なります。
result = [123, 456, 678, [111, 222]]
途中で次のextend
ようになります。
result = [123, 456, 678, 111, 222]
この質問に対する有用な補足を作成できることを願っています。たとえば、リストに特定のタイプのオブジェクトが格納されている場合、メソッドが適していないInfo
状況があります。ループ内で毎回オブジェクトを生成し、それをリストに格納するために使用すると、失敗します。例外は以下のようなものです:extend
for
Info
extend
TypeError: 'Info' オブジェクトは反復可能ではありません
しかし、append
メソッドを使用すると、結果は OK です。メソッドを使用するたびにextend
、常にリストまたはその他のコレクション型として扱われ、反復され、前のリストの後に配置されるためです。明らかに、特定のオブジェクトを反復することはできません。