リスト¶
基本¶
リストは複数の値・オブジェクトをまとめる.要素を,
で区切って並べ,全体を[
]
で囲んで作成する.
a = [0, 1, 4, 9, 16, 25, 36, 49]
a
[0, 1, 4, 9, 16, 25, 36, 49]
type(a)
list
先頭要素のインデックス番号は0.
a[0]
0
a[1]
1
リストの要素数はlen関数で取得する.
len(a)
8
要素の範囲を超えてリストにアクセスするとエラーになる.
a[8]
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-7-beec7994ef7f> in <module>
----> 1 a[8]
IndexError: list index out of range
リストの最後の要素のインデックス番号は「要素数 - 1」.
a[len(a)-1]
49
リストの要素を末尾からアクセスするため,負のインデックス番号を用いることができる.
a[-1]
49
a[-2]
36
空のリストは[]
かlist関数で作成する.
a = []
a
[]
a = list()
a
[]
スライス¶
a[start:end:step]
という形式で,リストの要素の部分列を抽出できる(「スライス」と呼ばれる).
start
: 抽出を開始する要素のインデックス番号.省略された場合は0
となる.end
: 抽出を終了する要素のインデックス番号(ただし,a[end]
の要素は含まれない).省略された場合はリストの要素数となる.step
: 要素を抽出する間隔.省略された場合は1
である.
a = [0, 1, 4, 9, 16, 25, 36, 49]
開始位置と終了位置を指定したスライス.
a[2:5]
[4, 9, 16]
a[0:3]
[0, 1, 4]
開始位置を省略したスライス.
a[:3]
[0, 1, 4]
終了位置を省略したスライス.
a[5:]
[25, 36, 49]
負のインデックス番号を用いてもよい.
a[-3:]
[25, 36, 49]
要素を取り出す間隔を指定したスライス.
a[1::2]
[1, 9, 25, 49]
間隔に-1
を指定して,逆順に要素を取り出すスライス(a[5]
, a[4]
, a[3]
が取り出される).
a[5:2:-1]
[25, 16, 9]
開始位置と終了位置を省略し,全ての要素を逆順に取り出すスライス.
a[::-1]
[49, 36, 25, 16, 9, 4, 1, 0]
リストの要素に対する繰り返し¶
a = [0, 1, 4, 9, 16, 25, 36, 49]
リストの要素に先頭から繰り返しアクセスする.
for x in a:
print(x)
0
1
4
9
16
25
36
49
リストの要素に先頭から繰り返しアクセスすると同時に,各要素のインデックス番号を得る.
for i, x in enumerate(a):
print(i, x, a[i])
0 0 0
1 1 1
2 4 4
3 9 9
4 16 16
5 25 25
6 36 36
7 49 49
リストの要素に末尾から繰り返しアクセスする.
for x in reversed(a):
print(x)
49
36
25
16
9
4
1
0
リストの要素に対する操作¶
wd = ['mon', 'tue', 'wed', 'thu', 'fri']
wd
['mon', 'tue', 'wed', 'thu', 'fri']
リスト内の要素を変更する.
wd[1] = 'tuesday'
wd
['mon', 'tuesday', 'wed', 'thu', 'fri']
末尾に要素を追加する.
wd = ['mon', 'tue', 'wed', 'thu', 'fri']
wd.append('sat')
wd
['mon', 'tue', 'wed', 'thu', 'fri', 'sat']
指定した要素を削除する.
del wd[5]
wd
['mon', 'tue', 'wed', 'thu', 'fri']
リストを連結して,新しいリストを作成する.
d = wd + ['sat', 'sun']
d
['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
リストをスタックと見なしてpop操作をすると,末尾の要素が取り出され,同時に末尾の要素がリストから削除される.
d.pop()
'sun'
d
['mon', 'tue', 'wed', 'thu', 'fri', 'sat']
push操作に相当するものはappend関数である.
d.append('sun')
d
['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
要素を降順に並べたリストを新たに作成する(この場合は辞書順に並ぶ).
sorted(d)
['fri', 'mon', 'sat', 'sun', 'thu', 'tue', 'wed']
元のリスト(d
)は変更されていない.
d
['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
要素を昇順に並べたリストを新たに作成する(この場合は辞書の逆順に並ぶ).
sorted(d, reverse=True)
['wed', 'tue', 'thu', 'sun', 'sat', 'mon', 'fri']
要素を降順に並び替える.今回は,リストd
の要素そのものが並び替えられる.
d.sort()
d
['fri', 'mon', 'sat', 'sun', 'thu', 'tue', 'wed']
要素を昇順に並び替える.
d.sort(reverse=True)
d
['wed', 'tue', 'thu', 'sun', 'sat', 'mon', 'fri']
ある要素がリストに含まれるかを調べる.
'sun' in d
True
ある要素がリストに含まれないかを調べる.
'sun' not in d
False
リストと参照¶
参照の代入¶
リストx
を作成する.
x = ['mon', 'tue', 'wed', 'thu', 'fri']
x
['mon', 'tue', 'wed', 'thu', 'fri']
変数y
を作成し,リストであるx
を代入する.
y = x
y
['mon', 'tue', 'wed', 'thu', 'fri']
リストy
に要素を追加してみる.
y.append('sat')
y.append('sun')
y
['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
(予想に反し)リストx
の要素も変更されている('sat'
と'sun'
が追加されている).
x
['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
これは,代入文y = x
が「変数y
を定義し,変数y
の参照先を変数x
の参照先と一致させる」という動作を行うからである.元々,変数x
はリストオブジェクトを参照していた(関連付けられていた)ので,そのリスト・オブジェクトに複数の変数x
とy
を経由してアクセスできるようになった.ひとつのオブジェクトの実体を複数の変数x
とy
が参照している状況であるので,いずれの変数を経由してもオブジェクトの内容を変更できるし,いずれの変数を評価しても同じ結果が得られる.
リストのコピー¶
先ほどと同様に,リストx
を作成する.
x = ['mon', 'tue', 'wed', 'thu', 'fri']
x
['mon', 'tue', 'wed', 'thu', 'fri']
変数y
を作成し,リストであるx
の全体のスライスx[:]
を代入する.このとき,x
のリスト・オブジェクトのコピーが作成され,変数y
はコピーを参照することになる.
y = x[:]
y
['mon', 'tue', 'wed', 'thu', 'fri']
先ほどと同様に,リストy
に要素を追加してみる.
y.append('sat')
y.append('sun')
y
['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
今回は,リストx
の要素は変更されない.これは,変数x
とy
が,それぞれ別のリスト・オブジェクトを参照しているからである.
x
['mon', 'tue', 'wed', 'thu', 'fri']
リストと関数の引数¶
引数で与えられたリストの末尾に'END'
を追加する関数append_endを定義する.
def append_end(s):
s.append('END')
以下のリストx
を引数として,関数append_endを呼び出す.
x = ['one', 'two']
x
['one', 'two']
append_end(x)
すると,呼び出し元の変数であるx
の内容が変化する.
x
['one', 'two', 'END']
数値や文字列を引数として関数に渡す場合と異なり,リストを引数として関数に渡すと,その関数内でそのリストに対する変更は,関数の呼び出し元にも波及する.
リストの様々な作成方法¶
range関数が表す範囲に対応するリストを作成するには,list関数を用いる.
a = list(range(10))
a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
a = list(range(1, 10, 2))
a
[1, 3, 5, 7, 9]
リストの要素はデータ型が異なってもよい.
b = [1, 'one', 'first']
b[0]
1
b[1]
'one'
(0を含む)自然数のリストをrange関数で作成する.
a = list(range(10))
a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
リストの内包表記¶
空のリストを作成する.
a2 = []
a2
[]
空のリスト(a2
)に要素を追加する
for i in range(10):
a2.append(i * 2)
a2
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
これは2の段の掛け算の結果を表している.
a2[7]
14
上記の処理はリストの内包表記を使って簡潔に書ける.ソースコードを左から”list of i times two for all i in the range of ten”のように英語読みをすると解釈しやすい.
a2n = [i * 2 for i in range(10)]
a2n
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
a2n[7]
14
3の段の掛け算も内包表記を使って簡潔に書ける.
[i * 3 for i in range(10)]
[0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
内包表記を入れ子にして,掛け算表を2次元配列(リスト)として作成する.
m = [[i * j for i in range(10)] for j in range(10)]
m
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18],
[0, 3, 6, 9, 12, 15, 18, 21, 24, 27],
[0, 4, 8, 12, 16, 20, 24, 28, 32, 36],
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45],
[0, 6, 12, 18, 24, 30, 36, 42, 48, 54],
[0, 7, 14, 21, 28, 35, 42, 49, 56, 63],
[0, 8, 16, 24, 32, 40, 48, 56, 64, 72],
[0, 9, 18, 27, 36, 45, 54, 63, 72, 81]]
m[2]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
m[2][3]
6
2次元配列作成時の注意¶
*
演算子を使うと,指定した値で初期化しながら,指定した要素数のリストを作る.
a = [0] * 10
a
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
これを拡張して,2次元配列を作ることもできるが,これは避けるべきである.
a = [[0] * 10] * 10
a
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
一見すると2次元配列が作成されたように見えるが,思わぬ落とし穴がある.以下のコードである要素を変更したつもりが,列全体の値が変更されてしまう.
a[3][5] = 2
a
[[0, 0, 0, 0, 0, 2, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 2, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 2, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 2, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 2, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 2, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 2, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 2, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 2, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 2, 0, 0, 0, 0]]
これは,[0] * 10
で1次元のリスト・オブジェクトが一つだけ作成され,その唯一のオブジェクトへの参照が全てのa[.]
にセットされただけであるからである.
指定したサイズのリストを作成するときに,内包表記を使うこともできる.
b = [0 for i in range(10)]
b
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
これを拡張して,2次元配列を作ることができる.
b = [[0 for i in range(10)] for j in range(10)]
b
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
こちらは,我々が通常期待する2次元配列として振る舞う.
b[3][5] = 2
b
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 2, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]