基本情報ではじめる Python (2) 配列 ~ リスト、タプル、文字列、集合、辞書の特徴


2021-05-11 更新

この連載では、プログラミングの入門者を対象として、基本情報技術者試験の出題範囲にテーマを絞って、 Python の言語構文とプログラムの読み方を説明します。

今回のテーマは、要素を持つデータ型(配列)であるリスト、タプル、文字列、集合、辞書の特徴です。

とても幅広いテーマなので、まずは、この記事で、概要をつかんでください。

配列の操作が苦手な人に朗報です!

基本情報技術者試験の午後試験の「データ構造およびアルゴリズム」には、配列の操作に関する問題がよく出ます。

たとえば、以下は、実際の試験問題に示されたプログラムの一部を抜粋して改変したものです。このプログラムは、要素数 num 個の配列 data を二分割して、前半部の要素を配列 data1 に格納し、後半部の要素を配列 data2 に格納します。

info編集部注: スマートフォンでご覧の際は、プログラムや表は横スクロールすると全文をご覧になれます

code出典:平成 22 年度 春期 午後 問 8
/* 配列を二分割する擬似言語のプログラム */
・num1 ← num ÷ 2
・num2 ← num - num1
■ i:0, i < num1, 1
|・data1[i] ← data[i]
■
■ i:0, i < num2, 1
|・data2[i] ← data[num1 + i]
■

これを見て「そうそう、こういうのが苦手なんです!」という人が多いでしょう。

そんな人に朗報です。 Python の問題には、このように配列をコツコツと操作するプログラムは、ほとんど出ないはずです。なぜなら、 Python の配列は、単なるデータの並びではなく、複数のデータと、データに対する様々な機能をまとめたオブジェクトだからです。

Python の配列を使うと、先ほどの擬似言語と同様の処理を、以下のように短く簡単に記述できます。

# 配列を二分割するPythonのプログラム
mid = num // 2		# 真ん中の要素の添字を得る
data1 = data[:mid]	# 真ん中より前の要素をdata1に格納する
data2 = data[mid:]	# 真ん中以降の要素をdata2に格納する

擬似言語のプログラムでは、変数 i をループカウンタとして繰り返し処理を行っていましたが、 Python のプログラムには、それがありません。 Python の配列には、指定した位置で要素を切り分ける「スライス」という機能があるからです(スライスの構文に関しては、後で説明します)。

コラム

配列の要素と添字
a = ["りんご", "みかん", "ぶどう"] のような配列があった場合、 “りんご”, “みかん”, “ぶどう” のことを要素と言います。
また、後でも詳しく紹介しますが、要素の順序を表す数値を添字と言います。上記の例では、添字 0 の要素は “りんご” です。

要素を持つデータ型とは?

先ほど「 Python の配列」と言いましたが、実際には、 Python には、擬似言語の配列と同じものはありません。

擬似言語の配列に相当するオブジェクトとして、

  • リスト
  • タプル
  • 文字列
  • 辞書
  • 集合

があり、これらを
「要素を持つデータ型(これは基本情報技術者試験のシラバスに示された呼び名です)」

「イテラブル( iterable = 繰り返し可能)」
と総称します。

図 要素があるデータ型の種類
ミュータブル イミュータブル
シーケンス
  • リスト( list クラス)
  • タプル( tuple クラス)
  • 文字列( str クラス)
コレクション
  • 辞書( dict クラス)
  • 集合( set クラス)

シーケンスとコレクション

要素を持つデータ型は、要素に順序がある「シーケンス」と、順序がない「コレクション」に分類されます。順序があるとは、個々の要素を添字で指定できる、ということです。

リスト、タプル、文字列は、シーケンスです。
辞書と集合は、コレクションです。

 

後で具体例を示しますが、辞書は、添字ではなく、キーで要素を指定します。キーとなる言葉で辞書を引くようなイメージです。
集合は、個々の要素ではなく、データの集まり、つまり集合を取り扱います。

このように、辞書と集合は、「個々の要素を添字で指定できない」というよりは、「個々の要素を添字で指定するような用途では使わない」のです。

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

要素を持つデータ型は、要素の値を変更できる「ミュータブル」と、変更できない「イミュータブル」にも分類できます。

リスト、辞書、集合は、ミュータブルです。
文字列とタプルは、イミュータブルです。

ミュータブルとイミュータブルの区別は、あまり気にする必要はありません。なぜなら、試験問題には、イミュータブルな要素の値を変更するような、構文的に間違ったプログラムが出ることはないからです。

 

Python のオブジェクトは、クラスとして定義されています。

リスト、タプル、文字列、辞書、集合は、それぞれ list クラス、 tuple クラス、 str クラス、 dict クラス、 set クラスとして定義されています。今回は、取り上げませんが、それぞれのクラスには、様々な機能が用意されています。

リスト、タプル、文字列の表記方法

リストは、要素をカンマで区切って並べて、全体を [ ] で囲みます。
タプルは、要素をカンマで区切って並べて、全体を ( ) で囲みます。
文字列は、文字の並びの全体を ' ' または " " で囲みます。

以下に例を示します。

codeリスト、タプル、文字列の例
>>> a = [1, 2, 3, 4, 5]		# リストa
>>> b = (6, 7, 8, 9, 10)	# タプルb
>>> c = "hello"			# 文字列c

左辺の変数に、右辺のリスト、タプル、文字列を代入していますが、これは、代入というよりは、右辺のリスト、タプル、文字列に名前を付けている、と考えてください。

ここでは、 Python の対話モードでプログラムを実行しています。プログラムの後にあるコメントは、説明の都合で付けたものです(これは、これ以降で示すプログラムでも同様です)。

リスト、タプル、文字列に共通した機能 1(添字による要素の指定)

シーケンス(順序があり、個々の要素を添字で指定できる)であるリスト、タプル、文字列には、共通した機能がいくつかあります。主な機能を紹介しましょう。

シーケンスの個々の要素は、

 名前[添字] 

という構文で指定できます。

添字は、先頭から順に 0, 1, 2 ・・・です。マイナスの添字を使うこともでき、この場合には、末尾から順に -1, -2, -3 です。タプル全体は ( と ) で囲み、文字列全体は ‘ と ‘ または ” と ” で囲みますが、どのシーケンスでも、個々の要素は、添字を [ ] で囲みます。

以下に例を示します。

code要素を添字で指定した例(先ほどのプログラムの続き)
>>> a[0]	# リストaの先頭の要素を読み出す
1		# 要素の値は1である
>>> b[0]	# タプルbの先頭の要素を読み出す
6		# 要素の値は6である
>>> c[0]	# 文字列cの先頭の要素を読み出す
'h'		# 先頭の要素は 'h' である
>>> a[-1]	# リストaの末尾の要素を読み出す
5		# 要素の値は5である
>>> b[-1]	# タプルbの末尾の要素を読み出す
10		# 末尾の要素は10である
>>> c[-1]	# 文字列cの末尾の要素を読み出す
'o'		# 末尾の要素は 'o' である

リスト、タプル、文字列に共通した機能 2(スライス)

シーケンスの要素は、

 名前[開始位置:終了位置:ステップ] 

という構文で、部分的に切り出せます。この機能を「スライス( slice = 断片)」と呼びます。

スライスによって、開始位置~終了位置未満の範囲の要素が、ステップごとに切り出されます。

開始位置を省略すると、先頭の要素から切り出されます。終了位置を省略すると末尾の要素まで切り出されます。ステップを省略すると、 1 個ごとに切り出されます。

以下に例を示します。

codeスライスで要素を部分的に切り出した例(先ほどのプログラムの続き)
>>> a[2:4:1]	# リストaのa[2]からa[4]未満の要素を1個ごとに切り出す
[3, 4]		# a[2]からa[3]の要素が切り出される
>>> b[2:4:1]	# タプルbのb[2]からb[4]未満の要素を1個ごとに切り出す
(8, 9)		# b[2]からb[3]の要素が切り出される
>>> c[2:4:1]	# 文字列cのc[2]からc[4]未満の要素を1個ごとに切り出す
'll'

スライスは、難しく感じるかもしれませんが、個々の要素を指定する 名前[添字] という構文の拡張バージョンだと思えばわかりやすいでしょう。

リスト、タプル、文字列に共通した機能 3( + 演算子と * 演算子)

 シーケンス1 + シーケンス2 

という構文で、 2 つのシーケンスを連結できます。

 シーケンス * 数値 

という構文で、シーケンスを数値の回数だけ繰り返して連結できます。

以下に例を示します。

codeシーケンスで + 演算子と * 演算子を使った例
>>> a + a			  # リストaとリストaを + 演算する
[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]	  # リストaとリストaが連結される
>>> b + b			  # タプルbとタプルbを + 演算する
(6, 7, 8, 9, 10, 6, 7, 8, 9, 10)  # タプルbとタプルbが連結される
>>> c + c			  # 文字列cと文字列cを + 演算する
'hellohello'			  # 文字列cと文字列cが連結される
>>> a * 3			  # リストaと3を * 演算する
[1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]  # リストaが3回連結される
>>> b * 3			  # タプルbと3を * 演算する
(6, 7, 8, 9, 10, 6, 7, 8, 9, 10, 6, 7, 8, 9, 10)  # タプルbが3回連結される
>>> c * 3			  # 文字列cと3を * 演算する
'hellohellohello'		  # 文字列cが3回連結される

辞書の表記方法と機能(キーによる要素の指定)

辞書は、

キー:バリュー

という形式の要素をカンマで区切って並べて、全体を { } で囲みます。

以下は、英語をキー(鍵 key )、それに対応した日本語をバリュー(値 value )とした辞書の例です。

code英語と日本語を対応付けた辞書の例
>>> d = {"apple":"リンゴ", "orange":"ミカン", "grape":"ブドウ"}  # 辞書d

辞書には、辞書ならではの機能があります。

それは、シーケンスの個々の要素を

 名前[キー] 

という構文で指定することです。 [ と ] の中にあるのが、添字ではなくキーであることに注目してください。このキーの指定によって、対応するバリューが得られます。

以下に例を示します。

code要素をキーで指定した例(先ほどのプログラムの続き)
>>> d["apple"]		# "apple" というキーに対応するバリューを得る
'リンゴ'		# "リンゴ" である
>>> d["orange"]		# "orange" というキーに対応するバリューを得る
'ミカン'		# "ミカン" である
>>> d["grape"]		# "grape" というキーに対応するバリューを得る
'ブドウ'		# "ブドウ" である

集合の表記方法と機能(集合演算)

集合は、要素をカンマで区切って並べて、全体を { } で囲みます。{ と } で囲むことは、辞書と同じですが、要素がキー:バリュー という形式ではないので、集合と辞書を区別できます。

以下は、集合の例です。

code集合の例
>>> e = {1, 2, 3, 4}	# 集合e
>>> f = {3, 4, 5, 6}	# 集合f

集合には、集合ならではの機能があります。それは、集合どうしで「交わり(積集合)」「結び(和集合)」などの集合演算ができることです。

交わりは、& 演算子で求められ、結びは | 演算子で求められます。集合どうしの演算結果は、集合になります。このように、個々の要素ではなく、要素の集まりを取り扱うから、集合なのです。

以下に例を示します。

code集合どうして演算を行った例(先ほどのプログラムの続き)
>>> e & f		# 集合eと集合fの交わりを求める
{3, 4}			# {3, 4} という集合が得られる
>>> e | f		# 集合eと集合fの結びを求める
{1, 2, 3, 4, 5, 6}	# {1, 2, 3, 4, 5, 6} という集合が得られる

要素があるデータ型の使い分け

要素があるデータ型が5種類もあるので、どのように使い分けたらよいか、混乱してしまうかもしれません。

「基本的にリストを使い、その他は、それぞれの独自の機能が活かせる場面で使う」と考えてください。

シーケンスで(順序があり、個々の要素を添字で指定できる)、ミュータブルである(要素の値を書き換えられる)リストは、擬似言語の配列に近いものです。したがって、特に理由がないなら、リストを使えばよいのです。

要素の値を変更することがないなら、イミュータブルの(要素の値を書き換えられない)タプルを使うとよいでしょう。
文字の並びを取り扱う場合は、当然ですが、文字列を使います。
添字ではなく、キーで要素を指定するなら、辞書を使います。
個々の要素ではなく、全体をまとめて取り扱うなら、集合を使います。

要素があるデータ型の使い分け

・特に理由がない
arrow_forward リストを使う
・要素の値を変更しない
arrow_forward タプルを使う
・文字の並びを取り扱う
arrow_forward 文字列を使う
・キーで要素を指定する
arrow_forward 辞書を使う
・要素をまとめて取り扱う
arrow_forward 集合を使う

いかがでしたか。要素を持つデータ型の種類と特徴がわかったでしょう。

この連載では、今後も、基本情報技術者試験を Python で受けるための知識を取り上げて行きます。

それでは、またお会いしましょう!

 

label 関連タグ
実は、午前試験を『免除』できます 独習ゼミで午前免除試験を受けた 86% の方が、
午前試験を免除しています。
2021 年 下期 試験向け
午前免除のチャンスは
6月10日 12時(正午)まで!
info_outline
2021 年 下期 試験向け
午前免除のチャンスは
6月10日 12時(正午)まで!
詳しく見てみるplay_circle_filled
label これまでの『基本情報ではじめるPython』の連載一覧 label 著者

『プログラムはなぜ動くのか』(日経BP)が大ベストセラー
IT技術を楽しく・分かりやすく教える“自称ソフトウェア芸人”

大手電気メーカーでPCの製造、ソフトハウスでプログラマを経験。独立後、現在はアプリケーションの開発と販売に従事。その傍ら、書籍・雑誌の執筆、またセミナー講師として活躍。軽快な口調で、知識0ベースのITエンジニアや一般書店フェアなどの一般的なPCユーザの講習ではダントツの評価。
お客様の満足を何よりも大切にし、わかりやすい、のせるのが上手い自称ソフトウェア芸人。

主な著作物

  • 「プログラムはなぜ動くのか」(日経BP)
  • 「コンピュータはなぜ動くのか」(日経BP)
  • 「出るとこだけ! 基本情報技術者」 (翔泳社)
  • 「ベテランが丁寧に教えてくれる ハードウェアの知識と実務」(翔泳社)
  • 「ifとelseの思考術」(ソフトバンククリエイティブ) など多数