ユーニックス総合研究所

  • home
  • archives
  • python-list-add

Pythonで配列(リスト)に要素を追加する方法【append, extend, insert, スライス】

  • 作成日: 2023-12-27
  • 更新日: 2024-01-01
  • カテゴリ: Python

Pythonで配列に要素を追加する

この記事ではPythonの配列(リスト)に要素を追加する方法を解説します。
要素の追加にはappend, extend, insert, スライスなどが使えます。
CPythonの実装についても解説していきます。

5. データ構造 — Python 3.12.1 ドキュメント

配列なのかリストなのか?

Pythonでは配列に相当するものはリストと呼ばれています。
リストというとリスト構造のことを思い出す人も多いかと思いますし、それじゃリスト構造で実装されているなら配列じゃないんじゃないか?
と考える人もいるかと思います。

それがPythonではリストの実装は動的配列で実装されています。
ですので名前はリストですが、中身は配列になっているということです。
このリストのことを配列と言っても間違いではないのですが、一般的にはこの配列はPythonではリストと呼ばれています。

CPythonとは?

CPythonとはPythonの実装の1つで、C言語で実装されています。
このCPythonをビルドするとPythonが生成されます。
CPythonはGitHubでソースコードが公開されています。

GitHub - python/cpython: The Python programming language

リストに要素を追加する方法

Pythonのリストに要素を追加するには以下の3つのメソッドが使えます。

  • append ... リストの末尾に要素を追加
  • extend ... リストにリストを繋げる
  • insert ... 指定の位置に要素を挿入する

またスライスを使ってもリストの特定の範囲に要素を挿入できます。

  • スライス ... スライスで範囲指定し代入して要素を挿入

これらの方法について順に解説していきます。

append

append()はリストのメソッドの1つです。
リストの末尾に要素を1つ追加します。

l = []  

l.append(1)  
l.append(2)  
l.append(3)  

print(l)  # [1, 2, 3]  

追加できる型は整数に限らずPyObjectに相当するオブジェクトは何でも追加できます。

l = []  

l.append(1)  # 整数  
l.append(1.23)  # 実数  
l.append(True)  # 真偽値  
l.append('string')  # 文字列  
l.append([1, 2, 3])  # リスト  
l.append((1, 2, 3))  # タプル  
l.append({1, 2, 3})  # 集合  
l.append({'a': 1, 'b': 2})  # 辞書  

print(l)  
# [1, 1.23, True, 'string', [1, 2, 3], (1, 2, 3), {1, 2, 3}, {'a': 1, 'b': 2}]  

append()はスライスで表現すると以下と同じになります。

l = []  

l[len(l):] = [1]  
l[len(l):] = [2]  
l[len(l):] = [3]  

print(l)  # [1, 2, 3]  

appendのCPythonの実装ですが、これはCPython/Objects/listobject.cに書かれています。
appendを実行するとPyList_Append()という関数が呼ばれます。

CPython(3.13)ではPyListを頻繁に使って実装されており、PyList_Append()printf()を入れるとログが大量に出ます。
そういう場合はPyList_Append()関数の先頭に以下のコードを追加します。

    // DEBUG  
    if (PyLong_Check(newitem)) {  
        long value = PyLong_AsLong(newitem);  
        printf("newitem value: %ld\n", value);  
    }  

newitemPyList_Append()の引数です。これが追加される要素になります。型はPyObject *になります。
上記ではPyLong_Check()newitemがPyLongかどうか調べて、PyLongだったらPyLong_AsLong()newitemlongの値にして出力しています。

このコードを加えてCPythonをビルドしてappend()を呼び出すと、呼び出しが確認できます。

>>> l = []  
>>> l.append(123)  
newitem value: 123  
newitem value: 123  
>>> l  
[123]  

extend

exnted()はリストにイテラブルオブジェクトを追加してリストを拡張するメソッドです。
イテラブルオブジェクトとはイテレーション可能なオブジェクトのことでたとえばリストやタプルがこれに当たります。

l = []  

l.extend([1, 2])  
l.extend([3, 4])  

print(l)  # [1, 2, 3, 4]  

タプルや集合、辞書もextend()に渡せます。

l = []  

l.extend((1, 2))  # タプル  
l.extend({3, 4})  # 集合  
l.extend({'a': 1, 'b': 2})  # 辞書  

print(l)  # [1, 2, 3, 4, 'a', 'b']  

辞書についてはキーが追加されます。値ではないです。
値をextendしたい場合は辞書のvalues()を使います。

l = []  

d = {'a': 1, 'b': 2}  

l.extend(d.values())  # 辞書  

print(l)  # [1, 2]  

extend()はスライスを使う場合は以下のコードと同じになります。

l = []  

l[len(l):] = [1, 2, 3]  
l[len(l):] = (4, 5, 6)  

print(l)  # [1, 2, 3, 4, 5, 6]  

extend()はCPython(3.13)ではCPython/Objects/listobject.clist_extend()関数が呼ばれます。
list_extend()staticな関数で、いわゆるC言語的なプライベートな関数になっています。
プライベートですが登録すればPyListのメソッドとして使えますのでそのような実装になっています。

extend()の呼び出しを確認したい場合はlist_extend()の先頭に以下のコードを追加します。

    // DEBUG  
    if (PyList_Check(iterable)) {  
        if (PyList_Size(iterable)) {  
            PyObject *o = PyList_GetItem(iterable, 0);  
            if (o && PyLong_Check(o)) {  
                long value = PyLong_AsLong(o);  
                printf("iterable first value: %ld\n", value);  
            }  
        }  
    }  

iterablelist_extend()の引数でこれはPyObject型のポインタです。
これがリストかどうかチェックし、サイズ(長さ)をチェックします。
そしてPyList_GetItem()でリストの最初の要素を取り出し、これがPyLongだったらその値を出力します。

>>> l = []  
>>> l.extend([123])  
iterable first value: 123  
>>> l  
[123]  

insert

insert()はリストのメソッドで指定の位置に要素を挿入します。
insert()の第1引数はリストの添え字です。この添え字の要素の直前に挿入されます。
第2引数は挿入したい要素です。

l = []  

l.insert(0, 100)  
print(l)  # [100]  

l.insert(0, 200)  
print(l)  # [200, 100]  

l.insert(1, 300)  
print(l)  # [200, 300, 100]  

insert()で挿入する要素もPyObjectであればなんでも挿入できます。

l = []  

l.insert(0, 1)  # 整数  
l.insert(0, 1.23)  # 実数  
l.insert(0, True)  # 真偽値  
l.insert(0, 'string')  # 文字列  
l.insert(0, [1, 2, 3])  # リスト  
l.insert(0, (1, 2, 3))  # タプル  
l.insert(0, {1, 2, 3})  # 集合  
l.insert(0, {'a': 1, 'b': 2})  # 辞書  

print(l)  
# [{'a': 1, 'b': 2}, {1, 2, 3}, (1, 2, 3), [1, 2, 3], 'string', True, 1.23, 1]  

第1引数の添え字がリストの長さを超えていた場合は、最後の要素として挿入されます。

l = []  

l.insert(100, 1)  
l.insert(100, 2)  
l.insert(100, 3)  

print(l)  # [1, 2, 3]  

また添え字が負数の場合は後方からの参照になります。

l = [1, 2, 3]  
l.insert(-1, 4)  
print(l)  
# [1, 2, 4, 3]  

l = [1, 2, 3]  
l.insert(-2, 4)  
print(l)  
# [1, 4, 2, 3]  

insert()の以下のコードはappend()と同じになります。

l = []  

l.insert(len(l), 1)  
l.insert(len(l), 2)  
l.insert(len(l), 3)  

print(l)  # [1, 2, 3]  

insert()はCPython(3.13)ではCPython/Objects/clinic/listobject.c.hlist_insert()が呼ばれます。

この関数の呼び出しをチェックするには以下のコードをこの関数に追加します。

    if (PyLong_Check(object)) {  
        long value = PyLong_AsLong(object);  
        printf("insert value: %ld\n", value);  
    }  

objectargsの1番目の要素です。
上記のコードではPyLong_Check()objectがPyLongかどうかチェックし、PyLongだったらPyLong_AsLong()longの値にして出力します。

>>> l = []  
>>> l.insert(0, 1)  
insert value: 1  
>>> l  
[1]  

スライス

スライスとは角かっこの中にコロンで区切って添え字を書く書式を言います。

lis[0:10]  

スライスは部分の要素列を取り出したり、特定の添え字より後の要素を切り落としたりする便利な機能です。
文字列やイテレーション可能なオブジェクトで利用できます。

また、挿入の場合はスライス+代入式で任意の位置に要素を挿入できます。

l = [1, 2, 3]  
l[0:0] = [4, 5]  
print(l)  
# [4, 5, 1, 2, 3]  

l = [1, 2, 3]  
l[1:1] = [4, 5]  
print(l)  
# [1, 4, 5, 2, 3]  

l = [1, 2, 3]  
l[0:2] = [4, 5]  
print(l)  
# [4, 5, 3]  

l = [1, 2, 3]  
l[0:3] = [4, 5]  
print(l)  
# [4, 5]  

上記を見てもわかりますが、l[1:1]のように指定するとその位置にイテラブルオブジェクトが挿入されます。
l[0:2]のように指定すると、添え字0, 1の要素が上書きされて挿入されます。

リストのスライスはCPython(3.13)ではCPython/Objects/listobject.clist_ass_slice()関数が呼び出されます。

この関数の引数のaがリストで、vが挿入するオブジェクトです。
引数のilowihighのスライスでの対応は以下の通りです。

lis[ilow:ihigh]  

コメントによると、この関数はvがNULLで、かつ(ihigh - ilow) <= 8の場合に呼び出しが失敗しないことが保証されているらしいです。
どういう理由で保証が効くのかは不明です。

関連記事
Djangoでオブジェクトを一括作成・更新【bulk_create, bulk_update】
DjangoのModel.objects.filter()の使い方【QuerySet】
Djangoのmodelのcreate()の使い方【Python】
Django入門: ルートの設定 ~ 簡単な一行掲示板アプリを作る その4【Windows10】
NumPyのappend()の使い方: 配列の末尾に要素を追加
Numpyのarangeの使い方: 指定範囲の数列を生成する
Python3でYoutube Data APIを使ってキーワード検索する
PythonからC言語(my.puts)を呼び出して実行する