Pythonでリストを使っていると、「特定の位置に要素を追加したい」と思うことがありますよね。
そんなときに便利なのが、insert()
メソッドです。
よくある使用場面:
- リストの先頭にヘッダーを追加
- 順序を保ちながら新しい要素を挿入
- ユーザーが指定した位置にデータを追加
- ソート済みリストへの適切な位置への挿入
- データの並び替えや整理
他の方法との比較:
# append()は末尾にしか追加できない
fruits = ["apple", "banana"]
fruits.append("orange")
print(fruits) # ['apple', 'banana', 'orange']
# insert()なら任意の位置に挿入可能
fruits = ["apple", "banana"]
fruits.insert(1, "grape")
print(fruits) # ['apple', 'grape', 'banana']
この記事では、Pythonのリスト操作メソッドinsert()
の基本構文・使い方・注意点・応用例までを、初心者にも分かりやすく丁寧に解説します。
第1章:insert()の基本構文と動作

基本構文
リスト.insert(インデックス, 値)
パラメータの説明:
- インデックス:挿入したい位置(0から始まる)
- 値:挿入したい要素(任意のデータ型)
基本的な動作
# 基本例:リストの途中に要素を挿入
fruits = ["apple", "banana", "orange"]
print(f"挿入前: {fruits}")
fruits.insert(1, "grape")
print(f"挿入後: {fruits}") # ['apple', 'grape', 'banana', 'orange']
動作の仕組み:
- 指定されたインデックスの位置に新しい要素を挿入
- 元々その位置以降にあった要素は右に1つずつシフト
- リストの長さが1つ増える
視覚的な理解
# インデックスと要素の関係
original = ["A", "B", "C", "D"]
# 0 1 2 3 (インデックス)
original.insert(2, "X")
# 結果: ["A", "B", "X", "C", "D"]
# 0 1 2 3 4 (新しいインデックス)
print(original) # ['A', 'B', 'X', 'C', 'D']
様々なデータ型での挿入
# 文字列の挿入
words = ["hello", "world"]
words.insert(1, "beautiful")
print(words) # ['hello', 'beautiful', 'world']
# 数値の挿入
numbers = [1, 3, 5]
numbers.insert(1, 2)
print(numbers) # [1, 2, 3, 5]
# リストの挿入(ネストしたリスト)
data = ["a", "b"]
data.insert(1, ["x", "y"])
print(data) # ['a', ['x', 'y'], 'b']
# 辞書の挿入
items = [{"name": "A"}, {"name": "C"}]
items.insert(1, {"name": "B"})
print(items) # [{'name': 'A'}, {'name': 'B'}, {'name': 'C'}]
第2章:insert()のインデックス指定の詳細
正のインデックスでの挿入
# 先頭への挿入(インデックス0)
numbers = [2, 3, 4]
numbers.insert(0, 1)
print(numbers) # [1, 2, 3, 4]
# 末尾の前への挿入
colors = ["red", "blue"]
colors.insert(1, "green")
print(colors) # ['red', 'green', 'blue']
# 複数回の挿入
items = ["item1"]
items.insert(0, "header") # ['header', 'item1']
items.insert(2, "item2") # ['header', 'item1', 'item2']
items.insert(1, "subheader") # ['header', 'subheader', 'item1', 'item2']
print(items)
負のインデックスでの挿入
# 負のインデックスの理解
data = ["A", "B", "C", "D"]
# 0 1 2 3 (正のインデックス)
# -4 -3 -2 -1 (負のインデックス)
# 最後から2番目の位置に挿入
data.insert(-1, "X") # 最後の要素の前に挿入
print(data) # ['A', 'B', 'C', 'X', 'D']
# さらに例
numbers = [10, 20, 30]
numbers.insert(-2, 15) # 20の前に15を挿入
print(numbers) # [10, 15, 20, 30]
範囲外インデックスの動作
# インデックスが大きすぎる場合
data = [1, 2]
data.insert(10, 3) # 末尾に追加される
print(data) # [1, 2, 3]
# インデックスが小さすぎる場合(負の値で絶対値が大きい)
data = [1, 2, 3]
data.insert(-10, 0) # 先頭に追加される
print(data) # [0, 1, 2, 3]
# 実用的な例:安全な挿入
def safe_insert(lst, index, value):
"""範囲外インデックスでも安全に挿入"""
max_index = len(lst)
if index > max_index:
index = max_index
elif index < -max_index:
index = 0
lst.insert(index, value)
data = [1, 2, 3]
safe_insert(data, 100, 4) # 末尾に追加
safe_insert(data, -100, 0) # 先頭に追加
print(data) # [0, 1, 2, 3, 4]
第3章:append()、extend()との違いと使い分け

各メソッドの比較
メソッド | 目的 | 使い方 | 挿入位置 | 挿入可能数 |
---|---|---|---|---|
insert() | 指定位置に要素を挿入 | list.insert(2, "x") | 任意の位置 | 1つの要素 |
append() | 末尾に要素を追加 | list.append("x") | 最後のみ | 1つの要素 |
extend() | 末尾に複数要素を追加 | list.extend(["x", "y"]) | 最後のみ | 複数要素 |
実際の使用例での比較
# 初期データ
base_list = ["a", "b", "c"]
# append()の使用
list1 = base_list.copy()
list1.append("d")
print(f"append(): {list1}") # ['a', 'b', 'c', 'd']
# extend()の使用
list2 = base_list.copy()
list2.extend(["d", "e"])
print(f"extend(): {list2}") # ['a', 'b', 'c', 'd', 'e']
# insert()の使用
list3 = base_list.copy()
list3.insert(1, "x")
print(f"insert(): {list3}") # ['a', 'x', 'b', 'c']
# 複数のinsert()操作
list4 = base_list.copy()
list4.insert(0, "start") # 先頭に追加
list4.insert(2, "middle") # 間に追加
list4.insert(-1, "end") # 最後の要素の前に追加
print(f"multiple insert(): {list4}") # ['start', 'a', 'middle', 'b', 'c', 'end']
パフォーマンスの考慮
import time
def benchmark_insertions(size=10000):
"""挿入操作のパフォーマンス比較"""
# append()のベンチマーク
test_list = []
start = time.time()
for i in range(size):
test_list.append(i)
append_time = time.time() - start
# insert(0, x)のベンチマーク(先頭挿入)
test_list = []
start = time.time()
for i in range(size):
test_list.insert(0, i)
insert_front_time = time.time() - start
# insert(末尾, x)のベンチマーク
test_list = []
start = time.time()
for i in range(size):
test_list.insert(len(test_list), i)
insert_end_time = time.time() - start
print(f"append() : {append_time:.4f}秒")
print(f"insert(0, x) : {insert_front_time:.4f}秒")
print(f"insert(末尾, x) : {insert_end_time:.4f}秒")
# benchmark_insertions(1000) # 小さなサイズでテスト
第4章:insert()の実用例と応用
1. ソート済みリストへの適切な位置への挿入
def insert_sorted(sorted_list, value):
"""ソート済みリストに値を適切な位置に挿入"""
for i, item in enumerate(sorted_list):
if value <= item:
sorted_list.insert(i, value)
return
# ループを抜けた場合は末尾に追加
sorted_list.append(value)
# 使用例
numbers = [1, 3, 5, 7, 9]
insert_sorted(numbers, 4)
print(numbers) # [1, 3, 4, 5, 7, 9]
insert_sorted(numbers, 0)
print(numbers) # [0, 1, 3, 4, 5, 7, 9]
insert_sorted(numbers, 10)
print(numbers) # [0, 1, 3, 4, 5, 7, 9, 10]
2. CSVデータにヘッダーを追加
def add_csv_header(data_rows, headers):
"""CSVデータの先頭にヘッダー行を追加"""
data_rows.insert(0, headers)
return data_rows
# 使用例
csv_data = [
["田中", "30", "エンジニア"],
["佐藤", "25", "デザイナー"],
["鈴木", "35", "マネージャー"]
]
headers = ["名前", "年齢", "職業"]
add_csv_header(csv_data, headers)
for row in csv_data:
print(", ".join(row))
# 名前, 年齢, 職業
# 田中, 30, エンジニア
# 佐藤, 25, デザイナー
# 鈴木, 35, マネージャー
3. リストの中間への複数要素挿入
def insert_multiple(lst, index, items):
"""指定位置に複数の要素を順番に挿入"""
for i, item in enumerate(items):
lst.insert(index + i, item)
# 使用例
alphabet = ["a", "b", "f", "g"]
insert_multiple(alphabet, 2, ["c", "d", "e"])
print(alphabet) # ['a', 'b', 'c', 'd', 'e', 'f', 'g']
# より効率的な方法(スライスを使用)
def insert_multiple_efficient(lst, index, items):
"""スライスを使った効率的な複数要素挿入"""
lst[index:index] = items
alphabet2 = ["a", "b", "f", "g"]
insert_multiple_efficient(alphabet2, 2, ["c", "d", "e"])
print(alphabet2) # ['a', 'b', 'c', 'd', 'e', 'f', 'g']
4. 条件付きでの要素挿入
class SmartList:
"""条件付き挿入機能を持つリストクラス"""
def __init__(self, data=None):
self.data = data or []
def insert_if_not_exists(self, index, value):
"""値が存在しない場合のみ挿入"""
if value not in self.data:
self.data.insert(index, value)
return True
return False
def insert_unique_sorted(self, value):
"""重複を避けながらソート順を保って挿入"""
if value in self.data:
return False
for i, item in enumerate(self.data):
if value < item:
self.data.insert(i, value)
return True
self.data.append(value)
return True
def __str__(self):
return str(self.data)
# 使用例
smart_list = SmartList([1, 3, 5])
smart_list.insert_unique_sorted(4) # True
smart_list.insert_unique_sorted(3) # False (already exists)
smart_list.insert_unique_sorted(0) # True
print(smart_list) # [0, 1, 3, 4, 5]
5. インタラクティブなリスト編集
def interactive_list_editor():
"""ユーザーがリストを対話的に編集できる関数"""
items = []
while True:
print(f"\n現在のリスト: {items}")
print("1. 要素を追加")
print("2. 特定位置に挿入")
print("3. 要素を削除")
print("4. 終了")
choice = input("選択してください (1-4): ")
if choice == "1":
value = input("追加する値: ")
items.append(value)
elif choice == "2":
try:
index = int(input("挿入位置: "))
value = input("挿入する値: ")
items.insert(index, value)
except ValueError:
print("有効な数値を入力してください")
elif choice == "3":
try:
index = int(input("削除する位置: "))
removed = items.pop(index)
print(f"'{removed}' を削除しました")
except (ValueError, IndexError):
print("有効な位置を指定してください")
elif choice == "4":
break
else:
print("1-4の数字を入力してください")
return items
# 使用例(実際に実行する場合)
# final_list = interactive_list_editor()
# print(f"最終的なリスト: {final_list}")
第5章:insert()の注意点とよくあるミス

注意①:insert()は破壊的メソッド(戻り値がNone)
# よくある間違い
items = [1, 2, 3]
result = items.insert(1, "new")
print(result) # None ← insert()は戻り値がない!
print(items) # [1, 'new', 2, 3] ← 元のリストが変更される
# 正しい理解
items = [1, 2, 3]
items.insert(1, "new") # 戻り値は使わない
print(items) # [1, 'new', 2, 3]
# 非破壊的な挿入が必要な場合
def non_destructive_insert(lst, index, value):
"""元のリストを変更せずに新しいリストを返す"""
new_list = lst.copy()
new_list.insert(index, value)
return new_list
original = [1, 2, 3]
modified = non_destructive_insert(original, 1, "new")
print(f"元のリスト: {original}") # [1, 2, 3]
print(f"新しいリスト: {modified}") # [1, 'new', 2, 3]
注意②:連続してinsert()を使う場合のインデックス変化
# 間違った理解:固定インデックスでの連続挿入
items = ["a", "c", "e"]
items.insert(1, "b") # ["a", "b", "c", "e"]
items.insert(3, "d") # ["a", "b", "c", "d", "e"] ← "c"の位置が変わっている
print(items) # ['a', 'b', 'c', 'd', 'e']
# 正しい理解:後ろから前に向かって挿入
items2 = ["a", "c", "e"]
items2.insert(2, "d") # 後の位置から先に挿入
items2.insert(1, "b") # 前の位置を後で挿入
print(items2) # ['a', 'b', 'c', 'd', 'e']
# または、挿入による位置変化を考慮
items3 = ["a", "c", "e"]
items3.insert(1, "b") # ["a", "b", "c", "e"]
items3.insert(3, "d") # ["a", "b", "c", "d", "e"]
print(items3) # ['a', 'b', 'c', 'd', 'e']
注意③:大きなリストでの先頭挿入のパフォーマンス
import time
def demonstrate_performance():
"""先頭挿入のパフォーマンス問題を実演"""
# 小さなリストでの先頭挿入
small_list = list(range(100))
start = time.time()
for i in range(100):
small_list.insert(0, i)
small_time = time.time() - start
print(f"小さなリスト(100要素)での先頭挿入: {small_time:.4f}秒")
# より効率的な方法:dequeを使用
from collections import deque
# dequeでの先頭挿入
deque_list = deque(range(100))
start = time.time()
for i in range(100):
deque_list.appendleft(i) # O(1)の操作
deque_time = time.time() - start
print(f"dequeでの先頭挿入: {deque_time:.4f}秒")
# demonstrate_performance()
注意④:異なるデータ型の混在
# 型の混在による問題
mixed_list = [1, 2, 3]
mixed_list.insert(1, "string")
mixed_list.insert(2, [4, 5])
print(mixed_list) # [1, 'string', [4, 5], 2, 3]
# 型安全な挿入
class TypeSafeList:
def __init__(self, expected_type, data=None):
self.expected_type = expected_type
self.data = data or []
# 初期データの型チェック
for item in self.data:
if not isinstance(item, expected_type):
raise TypeError(f"Expected {expected_type}, got {type(item)}")
def insert(self, index, value):
if not isinstance(value, self.expected_type):
raise TypeError(f"Expected {self.expected_type}, got {type(value)}")
self.data.insert(index, value)
def __str__(self):
return str(self.data)
# 使用例
int_list = TypeSafeList(int, [1, 2, 3])
int_list.insert(1, 5) # OK
print(int_list) # [1, 5, 2, 3]
try:
int_list.insert(0, "string") # TypeError
except TypeError as e:
print(f"エラー: {e}")
第6章:高度な活用パターン
bisectモジュールとの組み合わせ
import bisect
def optimized_sorted_insert(sorted_list, value):
"""bisectを使った効率的なソート済みリスト挿入"""
# 挿入位置を効率的に見つける(二分探索)
index = bisect.bisect_left(sorted_list, value)
sorted_list.insert(index, value)
# パフォーマンス比較
def compare_insertion_methods():
import time
import random
# テストデータの準備
size = 1000
sorted_data1 = list(range(0, size * 2, 2)) # 偶数のリスト
sorted_data2 = sorted_data1.copy()
test_values = [random.randint(0, size * 2) for _ in range(100)]
# 線形探索での挿入
start = time.time()
for value in test_values:
insert_sorted(sorted_data1, value)
linear_time = time.time() - start
# bisectを使った挿入
start = time.time()
for value in test_values:
optimized_sorted_insert(sorted_data2, value)
bisect_time = time.time() - start
print(f"線形探索: {linear_time:.4f}秒")
print(f"bisect使用: {bisect_time:.4f}秒")
print(f"bisectは約{linear_time/bisect_time:.1f}倍高速")
# compare_insertion_methods()
カスタムソート順での挿入
def insert_with_custom_order(lst, value, key_func=None):
"""カスタムソート順でリストに挿入"""
if key_func is None:
key_func = lambda x: x
target_key = key_func(value)
for i, item in enumerate(lst):
if target_key <= key_func(item):
lst.insert(i, value)
return
lst.append(value)
# 使用例:辞書のリストを名前順で挿入
people = [
{"name": "Alice", "age": 30},
{"name": "Charlie", "age": 25},
{"name": "Eve", "age": 35}
]
new_person = {"name": "Bob", "age": 28}
insert_with_custom_order(people, new_person, key_func=lambda p: p["name"])
for person in people:
print(f"{person['name']}: {person['age']}歳")
# Alice: 30歳
# Bob: 28歳
# Charlie: 25歳
# Eve: 35歳
まとめ
insert()
は、Pythonでリストを柔軟に扱うための基本的で重要なメソッドです。
位置を指定してデータを差し込む場面では、他のメソッドよりも圧倒的に便利です。
本記事の重要ポイント
基本的な使い方:
list.insert(インデックス, 値)
で任意の位置に挿入- 既存要素は右にシフトされ、リストの長さが1増える
- 負のインデックスも使用可能
重要な特徴:
- 破壊的メソッド:元のリストを変更し、戻り値は
None
- 範囲外インデックス:大きすぎれば末尾、小さすぎれば先頭に挿入
- パフォーマンス:先頭への挿入は要素数に比例して時間がかかる
他のメソッドとの使い分け:
append()
:末尾への単一要素追加extend()
:末尾への複数要素追加insert()
:任意位置への単一要素挿入
コメント