akuruhinode's blog

pythonやC#を中心に興味を持った内容について調べています。

Python リストとタプルの使い方

はじめに

連続した複数の要素を扱う際に利用するリストと、リストと似たような用途で利用されるタプルついて、基本的な使い方をサンプルコードを用いて説明します。

データ型

リストとタプルは連続した複数の要素を取り扱うことができるデータ型です。
厳密には、これらはシーケンス型と呼ばれるデータ型に含まれています。

リストの使い方

記述方法

リストの記述方法は以下の通りです。リストの値を要素と呼びます。

  • [](角かっこ)でくくる
  • 各要素をカンマで区切る
fruits= ['apple', 'banana', 'orange', 'grape'] # リストの作成

初期化

以下のように要素を含まない角かっこを指定するとリストを初期化できます。
この状態ではsampleは要素を持たない空リストの状態です。

sample = [] # 空リストの作成

要素の取得

単一の要素を取得

リストの各要素はインデックスを指定することで取得できます。
インデックスは0から始まります。

pythonでは負のインデックスを指定することもできます。

  • 1がリストの末尾を表し、-2, -3のように数値を小さくしていくことで末尾から2番目、3番目のように指定できます。
fruits = ['apple', 'banana', 'orange', 'grape']
print('[0]', fruits[0])  # 0番目の要素を取得
print('[2]', fruits[2])  # 2番目の要素を取得

print('[-1]', fruits[-1])  # 末尾(3番目)の要素を取得
print('[-3]', fruits[-3])  # 末尾から3番目の要素を取得
[0] apple
[2] orange
[-1] grape
[-3] banana
複製の要素をまとめて取得

スライスを利用するとリストから複数の要素をまとめて取得できます。スライスの評価結果は新規リストです。
スライスは2つの整数値を[1:3]のように[開始インデックス:終了インデックス+1]のように指定します。

注意点
2つめの数値はそのインデックス自身は含まれず、1つ小さいインデックスの要素が含まれます。

fruits = ['apple', 'banana', 'orange', 'grape']
print(fruits[1:3]) # 1,2番目の要素を取得
print(fruits[:2]) # 0,1番目の要素を取得
print(fruits[2:]) # 2番目から末尾までの要素を取得
print(fruits[2:-1]) # 2番目から末尾-1番目までの要素を取得
['banana', 'orange']
['apple', 'banana'] 
['orange', 'grape']
['orange']
リストの長さの取得

リストの長さを取得するにはlen()関数を利用します。

fruits = ['apple', 'banana', 'orange', 'grape']
print(len(fruits)) # リストの長さを取得
4

リストの操作

要素の変更

要素を変更するには、変更したい要素のインデックスを指定します。

fruits = ['apple', 'banana', 'orange', 'grape']
print(fruits) # 初期化後のリストを表示
fruits[1] = 'lemon'
print(fruits) # 要素変更後のリストを表示
['apple', 'banana', 'orange', 'grape']
['apple', 'lemon', 'orange', 'grape']
要素の追加

要素を末尾に追加するにはappend()メソッドを利用します。
要素を挿入するにはinsert()メソッドを利用します。

fruits = ['apple', 'banana', 'orange', 'grape']
print(fruits) # 初期化後のリストを表示
fruits.append('lemon')
print(fruits) # 要素追加後のリストを表示
fruits.insert(1, 'melon')
print(fruits) # 要素挿入後のリストを表示
['apple', 'banana', 'orange', 'grape']
['apple', 'banana', 'orange', 'grape', 'lemon']
['apple', 'melon', 'banana', 'orange', 'grape', 'lemon']

append()メソッド、insert()メソッドはリストそのものを変更します。関数の戻り値はNoneです。
None値については、以下の記事で説明しています。
akuruhinode.hatenablog.com

要素の削除

要素の値を指定して削除するにはremove()メソッドを利用します。

fruits = ['apple', 'banana', 'orange', 'grape']
print(fruits) # 初期化後のリストを表示
fruits.remove('orange')
print(fruits) # 削除後のリストを表示
['apple', 'banana', 'orange', 'grape']
['apple', 'banana', 'grape']

インデックスを指定して削除するにはdel文を利用します。この例では、remove('orange')と同じ結果が得られます。

fruits = ['apple', 'banana', 'orange', 'grape']
print(fruits) # 初期化後のリストを表示
del fruits[2]
print(fruits) # 削除後のリストを表示


remove()メソッドはリストそのものを変更します。関数の戻り値はNoneです。

要素の検索

index() メソッドを利用することで、ある要素がリストに含まれているかを検索できます。要素が含まれている場合は、そのインデックスを返します。

fruits = ['apple', 'banana', 'orange', 'grape']
print(fruits.index('orange')) # 'orange'のインデックスを表示
2

注意点
指定した値がリストに含まれていない場合はValueError例外を発生させます。
ほかのプログラミング言語にも似た関数はありますが、検索対象が見つからない場合は-1を返すことが多いと思います。

fruits = ['apple', 'banana', 'orange', 'grape']
print(fruits.index('lemon')) # 'lemon'(リストに存在しない値)のインデックスを表示
Traceback (most recent call last):
  File "sample.py", line 2, in <module>
    print(fruits.index('lemon'))
ValueError: 'lemon' is not in list


単純にある要素がリストにあるかどうかだけを知りたい場合は、in演算子not in演算子を利用できます。
in演算子を利用することで、リストに含まれるかを評価できます。
not in演算子を利用することで、リストに含まれていないかを評価できます。
これらは'orange' in fruitsのように検索対象 in リストの形で利用できますが、if文と合わせて利用することが多いと思います。

fruits = ['apple', 'banana', 'orange', 'grape']
if 'orange' in fruits: # 'orange'を含む場合True
    print('orangeを含む')
else:
    print('orangeを含まない')

if 'lemon' not in fruits: # 'lemon'を含まない場合True
    print('lemonを含まない')
else:
    print('lemonを含む')
orangeを含む
lemonを含まない
リストの連結

数学演算子の+演算子を利用することで、複数のリストを連結できます。

fruits = ['apple', 'banana', 'orange', 'grape']
vegetables = ['tomato', 'pumpkin']
foods = fruits + vegetables

print(fruits) # 1つめのリストを表示
print(vegetables) # 2つめのリストを表示 
print(foods) # 1つめのリストと2つめのリストの連結結果を表示
['apple', 'banana', 'orange', 'grape']
['tomato', 'pumpkin']
['apple', 'banana', 'orange', 'grape', 'tomato', 'pumpkin']

この+演算子では異なるデータ型を含むリストも連結できます。

リストの複製

リストは参照渡しされますので、別の変数に代入しても代入先のリストで要素を変更すると元のリストの要素も変わってしまいます。

fruits = ['apple', 'banana', 'orange', 'grape']
fruits_copy = fruits
fruits_copy[1] = 'lemon'
print(fruits) # 要素の変更後のリストを表示(copy元)
print(fruits_copy) # 要素の変更後のリストを表示(copy先)
['apple', 'lemon', 'orange', 'grape']
['apple', 'lemon', 'orange', 'grape']

元のリストの要素を変更せずリストを複製したい場合は、copyモジュールのcopy()関数を利用します。

import copy
fruits = ['apple', 'banana', 'orange', 'grape']
fruits_copy = copy.copy(fruits)
fruits_copy[1] = 'lemon'
print(fruits) # 要素の変更後のリストを表示(copy元)
print(fruits_copy) # 要素の変更後のリストを表示(copy先)
['apple', 'banana', 'orange', 'grape']
['apple', 'lemon', 'orange', 'grape']

注意点
copy()関数ではリストにリストが含まれていると内部のリストが参照渡しされてしまうため正しく複製されません。その場合はdeepcopy()関数を利用します。

copy()関数とdeepcopy()関数の違いについては、以下の記事で説明しています。
akuruhinode.hatenablog.com

リストの要素の複製

あるリストを別のリストに複製するのではなくリスト内の要素自体を複製する場合は、*演算子を利用できます。

fruits = ['apple', 'banana', 'orange', 'grape']
print(fruits) # 初期化後のリストを表示
fruits = fruits*2
print(fruits) # 要素の複製後リストを表示
['apple', 'banana', 'orange', 'grape']
['apple', 'banana', 'orange', 'grape', 'apple', 'banana', 'orange', 'grape']
ソート

sort()メソッドを利用すると、リストをソートできます。
sort(reverse=True)と指定すると、逆順にソートします。

fruits= ['apple', 'banana', 'orange', 'grape']
print(fruits) # 初期化後のリストを表示
fruits.sort()
print(fruits) # 昇順ソート後のリストを表示
fruits.sort(reverse=True)
print(fruits) # 逆順ソート後のリストを表示
['apple', 'banana', 'orange', 'grape']
['apple', 'banana', 'grape', 'orange']
['orange', 'grape', 'banana', 'apple']

注意点
リストに異なる型の要素を含むとソートできません。

その他の使い方

forループとの組み合わせ

forループを組み合わせることで、リストの値を順番に取得できます。forループとの組み合わせ方は2通りあります。
for 変数名 in リスト:とすることで、リストの要素が順番に変数に格納されます。
for 変数名 in range(len(リスト)):とすることで、リストのインデックスが順番に変数に格納されます。

fruits = ['apple', 'banana', 'orange', 'grape']
for fruit in fruits: # 要素を順番に取得
    print(fruit)

print('---')

for i in range(len(fruits)): # インデックスを順番に取得
    print(fruits[i])
apple
banana
orange
grape
---
apple
banana
orange
grape
異なる型を同一のリストに含める

リストには異なる型の要素を含めることができます。

fruits = ['apple', 1, -1.2, ['banana', 'orange']]

for i in range(len(fruits)):
    print(str(i) + ' ' + str(type(fruits[i]))) # 要素の型を表示
0 <class 'str'>
1 <class 'int'>
2 <class 'float'>
3 <class 'list'>

注意点
異なる型を含むリストでsort()メソッドを利用すると、TypeErrorが発生します。

タプルの使い方

リストとの違い

タプルはリストと似ていますが、以下が異なります。

  • ()(丸かっこ)でくくる
  • 要素を変更できない

それ以外はリストと同じです。以下のリストの使い方と同じように利用できます。サンプルコードの角かっこを丸かっこに置き換えてください。


以下では、type()メソッドを利用して型が異なることを確認しています。

fruits = ['apple', 'banana', 'orange', 'grape']
fruits_tuple=('apple', 'banana', 'orange', 'grape')
print(type(fruits)) #type()でリストの型を表示
print(type(fruits_tuple)) #type()でタプルの型を表示
<class 'list'>
<class 'tuple'>


リストのように途中で要素を変更することはできませんので、以下のようなコードはTypeErrorのエラーが発生します。

fruits = ('apple', 'banana', 'orange', 'grape')

# 以下はすべてエラーになる
fruits[1] = 'lemon'
fruits.append('lemon')
fruits.insert(1, 'melon')
fruits.remove('orange')
del fruits[2]

ミュータブルとイミュータブル

リストのように途中で要素を変更できる型をミュータブル(変更可能)といい、タプルのように途中で要素を変更できない型をイミュータブル(変更不可)といいます。

リストとタプルの変換

list()関数とtuple()関数を利用することで、リスト、タプルを相互変換できます。それぞれ以下のように利用します。

変換後のタプル = tuple(変換するリスト)
変換後のリスト = list(変換するタプル) 

リストとタプルの違いは、かっこの違いを除けばミュータブル(変更可能)か、イミュータブル(変更不可)かだけでした。そのため、それぞれ簡単に相互変換できます。

fruits = ['apple', 'banana', 'orange', 'grape']
fruits_tuple = tuple(fruits) # リストからタプルに変換
fruits_list = list(fruits) # タプルからリストに変換

print(type(fruits_tuple)) # リストからタプルへの変換後の型を表示
print(type(fruits_list)) # リストからタプルへの変換後の型を表示
<class 'tuple'>
<class 'list'>