PR

初心者のためのPython: リストとタプルでシーケンスを理解する

python
記事内に広告が含まれています。

シーケンスとは?

シーケンスは、ラベルが付いた長いロッカーの列のようなもので、プログラミングの世界における変数を表しています。

※ 他のプログラミング言語に慣れている方なら、シーケンスは同じ種類のデータを整理して管理する便利な方法だと考えると分かりやすいでしょう。

この例えで言うと、各ロッカーは1つの変数に対応し、それぞれ1つのデータ項目を格納します。しかし、シーケンスの利点は、複数の似たデータ項目を1つのグループとしてまとめることができる点にあります。ロッカーに固有の番号が付いているように、シーケンスも各要素を識別してアクセスするためのインデックスや位置で構成されています。この番号付けシステムにより、特定のデータの位置を忘れても、簡単に取り出すことができます。

要するに、シーケンスはさまざまなデータをまとめて管理し、数値インデックスによって順序付けたものです。この基本的な概念はPython初心者にとって非常に重要で、プログラム内で情報を整理して扱うための構造化された方法を提供します。

文字列

Pythonの文字列はシーケンスの一種であり、Python公式ドキュメントでは「テキストシーケンス型」と分類されています。つまり、文字列を扱うときは、文字のシーケンスを扱っているということになります。

例えば、次のような文字列を考えてみましょう:

word = "HelloWorld"

変数wordは「HelloWorld」という10文字の単語全体を含んでいるように見えますが、実際には10個の文字が順に並んだシーケンスです。具体的には、wordにはH、e、l、l、o、W、o、r、l、dの文字が順に含まれています。

この概念をわかりやすくするために、文字列をロッカーの列と考えてみましょう。Pythonではインデックスが "0" から始まり、変数wordの場合、最後のインデックスは "9" の合計10要素になります。

0123456789
HelloWorld
-10-9-8-7-6-5-4-3-2-1

さらに、ロッカーには負の番号も記載されています。これらの負のインデックスを使うと、シーケンスの最後から逆向きにたどることができます。例えば、"-1" は最後の要素を、"-2" は最後から2番目の要素を指します。このインデックスの付け方は、文字列の要素を柔軟に操作するのに役立ちます。

文字列をシーケンスとして理解し、正のインデックスと負のインデックスの両方を把握することは、文字列内の個々の要素を操作したりアクセスしたりするための基礎となります。これはPython初心者にとって非常に重要な概念です。

文字列のスライス

Pythonでは、スライシングは文字列に限らず、シーケンス全般に使える概念です。

スライシングは、シーケンスの一部を切り出す操作です。ここでは、文字列を例にスライシングを説明します。以下のような、a~zまでの小文字26文字からなる文字列を考えてみましょう:

a = "abcdefghijklmnopqrstuvwxyz"

このシーケンスから要素を抽出する方法を見ていきましょう。

特定の要素の取得

特定の要素を取り出すには、次の構文を使います:

文字列名[位置]

Pythonではインデックスがゼロから始まることに注意してください。

print(a[0])
print(a[10])
print(a[25])

出力は以下の通りです:

a
k
z

また、負の数を使ってシーケンスの末尾から要素を参照することもできます。

print(a[-1])
print(a[-10])
print(a[-26])

出力は以下の通りです:

z
q
a

負のインデックスは、シーケンスの末尾から要素にアクセスする便利な方法です。

文字列の一部を取り出す(スライス)

文字列の一部分を取り出す(スライシング)には、次の構文を使用します:

文字列名[開始位置:終了位置]

これにより、指定した開始位置から終了位置までの部分を取り出すことができます。ただし、終了位置には注意が必要です。例えば:

a = "abcdefghijklmnopqrstuvwxyz"
print(a[0:5])

出力は次のようになります:

abcde

つまり、「終了位置 - 1」 までの文字列が取得されています。上の例で言えば、0番目(a)~4番目(e)の5文字が取り出されました。この「終了位置 - 1」に慣れるまでしばらく混乱するかもしれません。

開始位置と終了位置を省略することもできます。開始位置を省略すると0から始まり、終了位置を省略すると文字列の最後までが選択されます。

print(a[:5])
print(a[5:])
print(a[:-15])
print(a[:])

出力は以下の通りです:

abcde
fghijklmnopqrstuvwxyz
abcdefghijk
abcdefghijklmnopqrstuvwxyz

さらに、スライスにはインクリメント(増加分)を指定することもできます。構文は次の通りです:

string_name[開始位置:終了位置:インクリメント]

例えば:

print(a[0:10:2]) # 0~10まで2つ飛ばしで取得
print(a[-1:-10:-2])

出力は次のようになります:

acegi
zxvtr

インクリメントが負の数の場合、取得される文字列は逆順になります。

これらのスライステクニックを理解することは、Pythonで文字列を操作し、必要なデータを抽出するために非常に重要です。

リスト

ここまでは、文字列を「各要素が1文字のロッカー」として説明しました。ここからは、より実用的なリストを紹介します。

リストは、2文字以上の文字列や、さまざまな数値を格納することができます。

角括弧([ ])によるリストの作成

リストは、要素を角括弧 [ ] で囲むことで簡単に作成できます。

a = [1, 5, 26]
b = ["a", "b", "c"]
c = []
d = [10, "car", 3, "train"]

空のリスト(変数 c)や、文字列と数値が混在するリスト(変数 d)も作成できます。

しかし、リストでは一般的に単一のデータ型に統一することが推奨されます。これは、後でデータを処理する際に予期せぬエラーを避けるためです。

また、type() を使って、変数がリストであることを確認することもできます。

type(b) # リストの型を確認

出力:

list

list() 関数によるリストの作成

もう一つのリストの作成方法として、list() 関数があります。この方法は、文字列や range() などの他のシーケンスをリストに変換する際に便利です。

# list() 関数によるリストの作成例
e = list("HelloWorld")
print(e)

f = list(range(1, 11, 2))
print(f)

g = list()
print(g)

出力:

['H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd']
[1, 3, 5, 7, 9]
[]

list() を文字列と一緒に使うと、各文字が個別の要素としてリストに格納されます。さらに変数g のように、list() を使って空のリストを作成することもできます。

リストはPythonの基本的かつ汎用的なデータ構造であるため、Python初心者がこれらの異なるリストの作成方法を理解することは非常に重要です。

リストの操作

Pythonのリストは要素の追加、削除、操作が容易にできる柔軟なデータ構造です。ここからはリストの基本操作を解説します。

リストの要素の参照

リスト内の要素を参照する際には、文字列のセクションで紹介した「スライス」記法を使うことができます。以下は、要素を参照するさまざまな方法です:

  • リスト[位置]
  • リスト[開始位置:終了位置]
  • リスト[開始位置:終了位置:増加分]

先に作成したリストe(['H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'])とリストf([1, 3, 5, 7, 9])を使って、これらの方法を試してみましょう。

print(f[1])
print(f[1:3])
print(e[1:8:2])

出力:

3
[3, 5]
['e', 'l', 'W', 'r']

新しい要素の追加

リストの末尾に要素を追加するには、append()メソッドを使用します。

months = ["January", "March"]
print(months)

months.append("April")
print(months)

出力:

['January', 'March']
['January', 'March', 'April']

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

特定の位置に要素を挿入したい場合は、insert()メソッドを使用します。

insert()関数では、リストの指定位置に要素を挿入することができます。基本形は以下の通りです。

list.insert(位置, 要素)

引数には、挿入する位置、挿入する要素の順に指定します。

months.insert(1, "February")
print(months)

出力:

['January', 'February', 'March', 'April']

これで、リストの1番目に"February"が挿入されましたね。

リストの結合

リストを結合することで、新しいリストを作成できます。結合には、「+」演算子を使用します。

a = [1, 2, 3]
b = [4, 5, 6]
c = a + b
print(c)

d = c + [7, 8, 9]
print(d)

出力:

[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7, 8, 9]

さらに、「*」演算子を使ってリストを繰り返し結合することもできます。

e = a * 3
print(e)

出力:

[1, 2, 3, 1, 2, 3, 1, 2, 3]

これらの操作を理解することは、Pythonでリスト内のデータを効率的に管理・操作するために非常に重要です。

文字列リストのソート

文字列のリストでは、sort() メソッドは要素をアルファベット順に並べ、reverse() は順序を逆にする。

friends = ["Tom", "John", "Carry", "Steve", "Nancy"]

friends.sort()
print(friends)

friends.reverse()
print(friends)

Output :

['Carry', 'John', 'Nancy', 'Steve', 'Tom']
['Tom', 'Steve', 'Nancy', 'John', 'Carry']

sort()reverse()も破壊的なメソッドであることに注意してください。

破壊的メソッド(デストラクティブメソッド)とは、オブジェクトの内容を直接変更するメソッドのことです。

上の例では、sort()reverse()も、変数friendsの要素を直接変更しているため、破壊的メソッドと呼ばれます。

非破壊ソート:

非破壊的メソッドとは、元のリストを変更せず、新しいリストを返します。

リストを非破壊でソートするには、 sorted() 関数を使用します。この関数は新しいソートリストを返し、元のリストは変更されません。引数 reverse でソートの順番を制御することができます。

num_lists = [3, 1, 4, 5, 2]
print(sorted(num_lists))
print(sorted(num_lists, reverse=True))
print(num_lists)

Output :

[1, 2, 3, 4, 5]
[5, 4, 3, 2, 1]
[3, 1, 4, 5, 2]

sorted() 関数で並び替えられた後、元の変数 num_listsは変更されず、そのままであることが分かりますね。

以下のように新しい変数に置き換えるのが一般的です。

num_lists = [3, 1, 4, 5, 2]
sorted_lists = sorted(num_lists)
reversed_lists = sorted(num_lists, reverse=True)

print(sorted_lists)
print(reversed_lists)
print(num_lists)

Output :

[1, 2, 3, 4, 5]
[5, 4, 3, 2, 1]
[3, 1, 4, 5, 2]

これらのメソッドを理解することで、リスト内の要素の順序を簡単に操作できるようになり、 Python でのさまざまなソートニーズに対応できるようになります。

反復処理とリスト

リストと反復処理を一緒に使うことで、動的にデータを構築して処理することができます。

cities = []

while True:
    city = input("都市名を入力 (Enterキーで終了): ")

    if city == "":
        break

    cities.append(city)

print("入力した都市名:")
for i in range(len(cities)):
    print(cities[i])

print("終了")

出力:

都市名を入力 (Enterキーで終了): 東京
都市名を入力 (Enterキーで終了): 大阪
都市名を入力 (Enterキーで終了): 名古屋
都市名を入力 (Enterキーで終了): 福岡
都市名を入力 (Enterキーで終了): 
入力した都市名:
東京
大阪
名古屋
福岡
終了

この例では、無限ループを使って、ユーザーが都市名を入力せずにEnterキーを押すまで、都市名を受信し続ける。append()メソッドは各都市名をリストに追加し、forループはリストを繰り返し、各要素を表示するコードです。

2次元リスト

2次元リストはテーブルのようなもので、縦と横のインデックスを使って要素にアクセスすることができます。2次元リストは以下のように作成し、アクセスすることができます.

1 2 3
4 5 6
7 8 9

上記の2次元リストをコードにすると以下のようになります。

twoD_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

もしくは、

twoD_lists = [
[1, 2, 3], 
[4, 5, 6], 
[7, 8, 9]
]

下の書き方の方が、視覚的に想像しやすいですね。それでは、この2次元リストの要素にアクセスします。

print(twoD_lists[0][2])
print(twoD_lists[2][1])

出力:

3
8

次に上のリストをrange()関数を使ってfor文で作成してみます。

rows = 3
cols = 3

list_2d = []
for i in range(rows):
    row = []
    for j in range(cols):
        row.append(i * cols + j + 1)
    list_2d.append(row)

print(list_2d)

出力:

[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

10~20個の要素なら手入力も可能ですが、膨大な数を作成する場合などは、上記のようなコードを書いてリスト作成するのが実用的となりますね。

zip()

zip()関数は、複数のリストをひとつにまとめる場合に便利な関数です。

names = ["優子", "剛", "五郎"]
sex = ["女性", "男性", "男性"]
scores = [95, 87, 92]

# zip()関数でリストを結合
combined_data = zip(names, sex, scores)

# リストに変換
combined_list = list(combined_data)

出力:

[('優子', '女性', 95), ('剛', '男性', 87), ('五郎', '男性', 92)]

ただし、新しいリストの各要素はタプルであり、結果として得られるリストはタプルを縦に並べたものであることに注意して下さい。

タプルとリストの違い

Pythonでは、タプルは順序付けられた不変の要素の集まりです。つまり、一度タプルを作成すると、その内容を変更することはできません。

タプルとリストはどちらも複数の要素を保持できる構造体ですが、重要な違いは変更可能性にあります。リストは作成後に要素を変更できるミュータブル(変更可能)な構造ですが、タプルは一度作成されると変更や追加、削除ができないイミュータブル(不変)な構造です。

Pythonにおけるタプルの存在には3つの主な目的があります:

  1. パフォーマンス: タプルは組み込み関数が少ないため、一般的にリストよりも高速です。
  2. 定数: タプルは定数値を格納するのに適しています。つまりデータ要素を意図的に変更することなく管理するのに役立ちます。
  3. 辞書のキー: タプルは辞書のキーとして使用することができます。

タプルの基本

タプルは要素を括弧 () で囲むことで定義します。以下はタプルの例です。

# 数値のタプル
numbers = (1, 2, 3)

# 文字列のタプル
words = ("apple", "banana", "cherry")

# 混合型のタプル
mixed = (1, "apple", 3.14)

# タプル内のタプル
nested = (1, (2, 3), "banana")

タプルはその内容を変更できないため、要素を変更しようとすると以下の様にエラーとなります。

numbers = (1, 2, 3)
numbers[0] = 10  # エラー: 'tuple' object does not support item assignment

タプルの利点

タプルはリストとは異なり、固定された構造です。このため、プログラム全体で一貫して保持されるべき関連情報を格納するのに便利です。例えば、座標や設定値などです。

# 座標の例
coordinate = (10.0, 20.0)

# 設定値の例
settings = ("dark_mode", True, 30)

タプルの要素へのアクセス

タプルの要素にはインデックスを使ってアクセスできます。インデックスは0から始まります。

coordinate = (10.0, 20.0)

# 最初の要素にアクセス
print(coordinate[0]) 

# 2番目の要素にアクセス
print(coordinate[1]) 

出力:

10.0
20.0

タプルの作成

タプルは括弧()を使用して作成されます。

fruits_tuple = ('リンゴ', 'バナナ', 'オレンジ', 'ブドウ')
print(fruits_tuple)

出力:

('リンゴ', 'バナナ', 'オレンジ', 'ブドウ')

リストとは異なり、タプルに新しい要素を追加することはできません。

しかし、タプルを格納する変数は再代入することができます。

fruits_tuple = ("青リンゴ", "桃", "メロン", "イチゴ")
print(fruits_tuple)

出力:

('青リンゴ', '桃', 'メロン', 'イチゴ')

" + "と " * "演算子はタプルに対して非破壊的であり、元のタプルを変更することなく連結や繰り返しができます。

a = (1, 2, 3)
b = (4, 5, 6)
c = a + b
d = c * 2

print(c)
print(d)

出力:

(1, 2, 3, 4, 5, 6)
(1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6)

タプルを理解することで、Pythonで効率的なデータ構造を設計する能力が高まります。

tuple() によるタプルの作成

tuple()関数は様々なシーケンスからタプルを作成する汎用的なツールです。

a = tuple("HelloWorld")

print(a)

出力:

('H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd')

タプルの使用

タプルはリストとは異なる特徴がありますが、要素の参照や検索は同じように可能です。

要素の参照

リストと同様に、スライスはタプル内の要素を参照するために使用されます。

a = tuple("HelloWorld")
print(a[2:5])

出力:

('l', 'l', 'o')

要素の取得

タプルには、要素を取得するためにcount() 関数と index() 関数を使うことが可能です。

a = tuple("HelloWorld")
print(a.count("l"))
print(a.index("W"))
print("e" in a)

出力 :

3
5
True

まとめ

今回は、シーケンス、リスト、タプルについて解説しました。シーケンスは順序付けられた要素の集まりであり、Pythonは文字列、リスト、タプルといったシーケンスタイプをサポートしています。
シーケンスの要素にはインデックスを通してアクセスでき、スライスを用いて複数の要素を抽出することができます。
リストは多用途で変更可能なシーケンスで、要素の変更、追加、削除が可能でありる、一方、タプルは不変のシーケンスで、作成後に要素を変更することはできません。これらの知識を応用してさらなるPythonプログラミングに進んでください。

コメント