M.Hiroi's Home Page
http://www.geocities.jp/m_hiroi/

Lightweight Language

お気楽 Python プログラミング入門

第 1 回 データ型と制御構造

[ PrevPage | Python | NextPage ]

はじめに

Python (パイソン) は Guido van Rossum によって開発されたオブジェクト指向スクリプト言語です。現時点でもっとも普及しているスクリプト言語は Perl になるでしょう。日本では知名度の低い Python ですが、海外では Perl の次に人気のあるスクリプト言語として広く普及しています。

Perl はバージョン 5 から「オブジェクト指向」や「リファレンス」など高度な機能が追加され、汎用のプログラミング言語として様々な分野で使われるようになりました。しかしながら、これらの機能が追加されたことにより、Perl はよりいっそう複雑な言語になってしまったように思います。

これに対し Python は、文字列、リスト、タプル、ディクショナリといった高水準のデータ型や、オブジェクト指向機能、モジュール機能、例外処理など高度な機能をサポートしていながら、シンプルでわかりやすいプログラミング言語になっています。実際、これらの機能は Perl よりも使いやすいと思います。このため、プログラミング入門に Python を勧める方も多いようです。

また、Python はスクリプトだけではなく、大規模なソフトウェア開発にも対応できる実用的な言語として使用することができます。多くのライブラリが標準で添付されているので、複雑な処理でもライブラリを使って簡単にプログラムを実装することができます。ライブラリの充実ぶりは Perl に勝るとも劣らないと思います。

そして、ブロック構造を表すのにインデント(字下げ)を用いるのが最大の特徴でしょう。C言語や Perl のように { ... } でブロックを表すのではなく、インデントの深さでブロックを表します。好き嫌いが分かれるところですが、誰が書いても同じようなプログラムになるので、可読性が高くなるという利点があります。慣れてしまえば問題はありません。

このように、高いポテンシャルを持つ Python ですが、日本ではあまり普及していません。近年、コンピュータの性能は著しく向上しているので、大きなプログラムをスクリプト言語で開発する機会はこれからも増えていくことでしょう。プログラムの保守性を考えると、可読性の高い Python は Perl よりも有利であり、今後は日本でも普及が進むものと思われます。

本連載では、簡単なプログラムを作りながら Python の基本からオブジェクト指向機能まで、プログラミング言語としての Python の機能を一通り説明していきたいと思っております。よろしくお付き合いください。

●Python のインストールと起動

Python の処理系は Python Programming LanguagePython Japan User's Group からダウンロードできます。Windows 用のインストーラも用意されているので簡単にインストールすることができます。

Python がインストールされていれば、シェル (Windows の場合はコマンドプロンプト) で python と入力します。または、Python に付属している GUI アプリケーション IDLE を起動してください。すると、メッセージとプロンプト '>>>' が表示され、対話モードで Python が起動されます。Python を終了するには Ctrl + D (Windows の場合は Ctrl + Z) を入力してください。

●Python のプログラム

Python は Perl やC言語と同じく、手続き型のプログラミング言語です。Python も Perl と同様に、プログラムの実行を制御する「文」、データを格納する「変数」、決められた処理を行う「関数」があります。

C言語や Perl は文の最後をセミコロン ( ; ) で区切りますが、Python はセミコロンを付ける必要はありません。関数は Python にあらかじめ用意されている「組み込み関数」のほかに、私達ユーザが定義することもできます。もちろん「再帰呼び出し」も可能です。

Python にはいろいろなデータが用意されています。データの種類を「データ型」と呼びます。Python の場合、基本的なデータ型には「数」と「文字列」があります。高水準なデータ型として「リスト」、「タプル」、「ディクショナリ」、「セット」があります。

また、Python はオブジェクト指向プログラミング (OOP) に対応しているので、「クラス」、「インスタンス」、「メソッド」、「継承」など OOP 的な機能があります。このほかに「モジュール機能」や「例外処理」といった高度な機能もサポートされています。

Python のプログラムで使用される変数名、関数名などには、英数字とアンダースコア _ が使えます。英大文字と英小文字は区別されるので、FOO と Foo と foo は異なる名前と判断されます。

本稿では Python 2.4 を基準に機能を説明します。2.4 以外の Python では動作しない機能もあります。ご注意ください。

●Python のデータ型

Python に用意されている基本的なデータ型について簡単に説明します。

●数

Python には整数 (integer)、浮動小数点数 (floating-point number)、複素数 (complex number) という 3 種類の数が用意されてます。簡単な例を示します。

>>> a = 100
>>> a
100
>>> print a
100
>>> b = 1.234
>>> b
1.234
>>> c = 2 ** 100
>>> c
1267650600228229401496703205376L
>>> d = 1 + 2j + 3 - 4j
>>> d
(4-2j)

Python はC言語と違い、あらかじめ変数やそのデータ型を宣言する必要はありません。変数に値をセットすることを「代入」といいます。代入には = を使います [*1]。これはC言語や Perl と同じです。対話モードで変数名を入力するとその値が表示されます。もしくは print 文を使って表示します。print 文は指定されたデータを画面(標準出力)へ出力して改行します。

変数 a には整数 100 を代入し、変数 b には実数 1.234 を代入しています。Python の整数には桁数の制限がありません。** はべき乗を計算する演算子で、2 の 100 乗のような大きな値でも計算することができます。算術演算子を表 1 に示します。

表 1 : 算術演算子
操作結果
-x x を負にする
x + y x と y の和
x - y x と y の差
x * y x と y の積
x / y x 割る y の商
x % y x 割る y の剰余
x ** y x の y 乗

浮動小数点数はC言語の倍精度浮動小数点数 (double) と同じで、範囲は約 1e-307 から 1e+308 までです。複素数は (実数部 + 虚数部) で表します。虚数単位は J または j を使って表します。j だけだと変数と認識されるので、1j と書くことに注意してください。

-- note --------
[*1] 代入は x = y = z = 0 のように、複数の変数に同じ値を代入することができます。

●文字列

文字列 (string) はシングルクオート ' で囲むか、ダブルクオート " で囲んで表します。

>>> a = 'hello, world'
>>> a
'hello, world'

変数 a には文字列 'hello, world' を代入しています。文字列には演算子 + と * を適用することができます。

>>>'abc' + 'def'
'abcdef'
>>>'abc' * 3
'abcabcabc'

演算子 + は文字列を連結した新しい文字列を作り、演算子 * は文字列を指定した回数だけ繰り返した新しい文字列を作ります。

文字列には「エスケープシーケンス」を含めることができます。これは、画面に表示することができない文字を表すのに用いられる方法です。よく使われる記号に改行を表す \n とタブを表す \t があります。

>>> print 'abc\ndef'
abc
def
>>> print 'abc\tdef'
abc    def

この例はタブが 4 文字に設定されている場合です。エスケープシーケンスを無効にしたい場合は、文字列の前に r または R を付けます。これを raw string といいます。

>>> print 'abc\ndef'
abc\ndef
>>> print 'abc\tdef'
abc\tdef

また、Python は unicode をサポートしています。文字列の前に u または U を付けると、その文字列は unicode に変換されます。

複数の行にわたって文字列を定義したい場合は継続行を使います。継続行は最後にバックスラッシュ (円記号) を付けます。

>>> b = 'abcdef\n\
012345\n\
ghijkl\n'
>>> b
'abcdef\n012345\nghijkl\n'
>>> print b
abcdef
012345
ghijkl

もうひとつ、三重のクオート """ または ''' で囲む方法 [*2] があります。簡単な例を示しましょう。

>>> c = '''abcdef
012345
ghijkl
'''
>>> c
'abcdef\n012345\nghijkl\n'
>>> print c
abcdef
012345
ghijkl

''' で囲まれた入力データがそのまま文字列になります。改行文字も含まれるので、継続行のように \n を付加する必要はありません。

-- note --------
[*2] Perl や UNIX 系のシェルにあるヒアドキュメント (here-document) という機能とよく似ている方法です。

●リスト

Python のリスト (list) [*3] はデータを一列に並べたもので、Perl の配列やC言語の 1 次元配列と同様のデータ構造です。リストに格納されたデータを「要素」といいます。リストの要素は整数値で指定します。これを「添字 (subscripts) 」といいます。Python の場合、C言語と同じく添字は 0 から始まります。

リストは角カッコ '[' と ']' で囲み、要素をカンマ ( , ) で区切って表します。[ ] は要素が一つもない空リストになります。簡単な例を示します。

>>> list1 = [10, 20, 30, 40, 50]
>>> a = list1[0]
>>> a
10
>>> list1[4] = 100
>>> list1
[10, 20, 30, 40, 100]
>>> list1[-1]
100
>>> list1[-2]
40

C言語は配列の大きさを宣言する必要がありますが、Python のリストは大きさを宣言する必要はありません。リストの大きさは Python が自動的に調整してくれます。大きさを自由に変えることができる配列を「可変長配列」といいます。他のスクリプト言語、たとえば Perl でも可変長配列をサポートしています。

リストの要素は角カッコ [ ] を使ってアクセスします。これはC言語や Perl と同じです。リストの要素を取り出して変数に代入することも、リストの要素を書き換えることもできます。添字に負の整数を指定すると、リストの後ろから数えます。list1[-1] は最後尾の要素 100 になり、list1[-2] は後ろから 2 番目の要素 40 になります。

リストの要素には、いろいろなデータ型が混在していてもかまいません。また、要素に式を書くこともできます。

>>> list2 = ['a', 10, 'b', 20, 'c', 30]
>>> list2[2]
'b'
>>> list2[3]
20
>>> [1 + 2, 3 - 4, 5 * 6]
[3, -1, 30]

list2 のリストは、0, 2, 4 番目の要素が文字列で、1, 3, 5 番目の要素が整数になっています。要素に式を書くと、その式の評価結果が要素になります。

リストは入れ子にすることができます。つまり、リストの要素にリストを入れてもかまいません。これで多次元配列を表すことができます。

>>> list3 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> list3[0]
[1, 2, 3]
>>> list3[0][1]
2

list3 のように、リストの中にリストを入れることで 2 次元配列を表すことができます。list3 の 0 番目の要素はリスト [1, 2, 3] で、そのリストの 1 番目の要素は 2 です。この要素は角カッコを 2 つ使って list3[0][1] とアクセスすることができます。list3[0] で 0 番目のリストを取り出し、そのリストの 1 番目の要素を [1] で取り出します。

-- note --------
[*3] リスト操作が得意なプログラミング言語では Lisp が有名です。Lisp のリストは連結リスト (linked list) のことですが、Python のリストは可変長配列として実装されています。

●タプル

タプル (tuple) は更新不能 (immutable) なリストのことです。リストは要素の値を書き換えることができますが、タプルはできません。タプルは丸カッコ '(' と ')' で囲み、要素をカンマ ( , ) で区切ります。( ) は空タプルを表します。リストと同様に、要素はいろいろなデータ型が混在してもかまいません。

簡単な例を示します。

>>> a = (1, 2, 3, 4)
>>> a
(1, 2, 3, 4)
>>> b = (5, 6, 7, 8)
>>> b
(5, 6, 7, 8)
>>> a[0]
1
>>> b[1]
6
>>> a + b
(1, 2, 3, 4, 5, 6, 7, 8)
>>> b * 2
(5, 6, 7, 8, 5, 6, 7, 8)

タプルを生成して変数 a と b にセットします。タプルはリストと同じく角カッコ [ ] で要素を取り出すことができます。ただし、a[0] = 10 のような代入操作はできません。

タプルは、丸カッコを省略しても生成できる場合があります。

>>> c = 1, 2, 3
>>> c
(1, 2, 3)
>>> d = [1, 2, (3, 4, 5)]
>>> d
[1, 2, (3, 4, 5)]

このように、カンマで区切られたデータはタプルに格納されます。ただし、リストやタプルの中にタプルを入れる場合などでは、丸カッコで囲む必要があります。

また、タプルを使って複数の変数に値を代入することができます。

>>> a = 1, 2, 3
>>> a
(1, 2, 3)
>>> x, y, z = a
>>> x
1
>>> y
2
>>> z
3

変数 x にはタプルの 0 番目の要素、y には 1 番目の要素、z には 2 番目の要素が代入されます。なお、リストを使っても変数に値を代入することができます。

>>> a = [10, 20, 30]
>>> a
[10, 20, 30]
>>> x, y, z = a
>>> x
10
>>> y
20
>>> z
30

x, y, z はタプル (x, y, z) ですが、リスト [x, y, z] にしても動作します。

>>> [x, y, z] = [100, 200, 300]
>>> x
100
>>> y
200
>>> z
300

要素が一つのタプルは、要素の後ろにカンマを付ける必要があります。次の例を見てください。

>>> a = 1,
>>> a
(1,)

演算の順序を指定するための丸カッコと区別するため、要素の後ろにカンマを付けます。要素が一つのタプルを生成する場合も、a = 1, のようにカンマを付けます。

●シーケンス

リスト、タプル、文字列はデータを一列に並べたデータ構造という共通点があります。このようなデータ型を「シーケンス(sequence) 」といいます。Python にはシーケンスに適用できる共通の操作があり、角カッコ [ ] は文字列にも適用できます。

>>> s = 'abcdef'
>>> s[0]
'a'

Python には「文字」を表すデータ型がないので、s[0] の値は文字列 'a' になります。また、Python の文字列は更新不能なので、値を書き換えることはできません。s[0] = 'A' のように代入操作を行うとエラーになります。

スライスはシーケンスの部分列を取り出す操作です。表 2 にスライス操作を示します。

表 2 : スライス操作
操作意味
S[start:end] start から end - 1 まで
S[start:] start から最後尾まで
S[:end] 先頭から end - 1 まで
S[:] 先頭から最後尾まで

S はシーケンスを表します。スライスによって取り出された部分列は元のシーケンスをコピーしたものです。start と end に部分列を指定します。start の位置の要素が部分列の先頭になり、end - 1 の要素が最後尾になります。start が省略されると先頭 (0) に、end が省略されるとシーケンスの要素数に設定されます。どちらも省略するとシーケンスをコピーすることになります。簡単な例を示します。

>>> s = [0, 1, 2, 3, 4, 5, 6, 7]
>>> s[2:6]
[2, 3, 4, 5]
>>> s[2:]
[2, 3, 4, 5, 6, 7]
>>> s[:6]
[0, 1, 2, 3, 4, 5]

演算子 + と * はリストやタプルにも適用することができます。次の例を見てください。

>>> [1, 2, 3] + [4, 5, 6]
[1, 2, 3, 4, 5, 6]
>>> [0] * 8
[0, 0, 0, 0, 0, 0, 0, 0]

シーケンスに格納されている要素数は関数 len() で求めることができます。len() は length のことで、シーケンスの要素数を「長さ」といいます。

>>> len([1, 2, 3])
3
>>> len('abcde')
5

関数 list() はシーケンスをリストに変換します。次の例を見てください。

>>> list([1, 2, 3])
[1, 2, 3]
>>> list((10, 20, 30))
[10, 20, 30]
>>> list('abcd')
['a', 'b', 'c', 'd']
>>> list()
[]

list() の引数にリストを与えると、そのリストをコピーした新しいリストを返します。文字列の場合は、1 文字ずつ分解してリストに格納します。引数がない場合は空リストを返します。このほかに、シーケンスをタプルに変換する関数 tuple() もあります。

●リストだけに適用できる操作

リストは文字列やタプルと違って値を更新できるので、リストにだけ適用できる操作が用意されています。主な操作を表 3 に示します。

表 3 : リストに適用できる主な操作
操作意味
L.append(x) 最後尾に要素を追加する
L.index(x) 要素 x を探して位置を返す
L.insert(i,x) i 番目に要素 x を挿入する
L.pop() 最後尾から要素を削除する
L.remove(x) 要素 x を削除する
del L[i] i 番目の要素を削除する
L[s:e] = List スライスへの代入

L はリストを表します。リストの操作はメソッド (method) として定義されています。メソッドは次の形式で呼び出します。

object.method(args, ...)

object はデータのことで、その後ろにドット ( . ) を付けて、メソッド名と引数を続けて書きます。Python はオブジェクト指向プログラミング言語なので、すべてのデータをオブジェクトとして扱うことができます。メソッドはオブジェクトを操作する関数のことで、Python では多くの操作がメソッドとして定義されています。オブジェクト指向機能はあとで詳しく説明します。

これらの操作は要素の探索を除いて、リストをコピーせずに直接書き換えることに注意してください。このような操作を「リストを破壊的に修正する」とか「破壊的な操作」といいます。簡単な例を示します。

>>> list1 = [1, 2, 3]
>>> list1.append(4)
>>> list1
[1, 2, 3, 4]
>>> list1.pop()
4
>>> list1
[1, 2, 3]
>>> list1.insert(0, 10)
>>> list1
[10, 1, 2, 3]
>>> list1.remove(2)
>>> list1
[10, 1, 3]
>>> list1.index(1)
1

このように、リストを破壊的に修正するので、変数 list1 の値は書き換えられたリストになります。

スライスへの代入は強力な操作です。指定した部分列を削除し、その部分に右辺のリストを挿入します。簡単な例を示します。

>>> list1 = [1, 2, 3, 4, 5]
>>> list1[2:3]
[3]
>>> list1[2:3] = [100, 200]
>>> list1
[1, 2, 100, 200, 4, 5]
>>>list1[2:2]
[]
>>> list1[2:2] = [10, 20]
>>> list1
[1, 2, 10, 20, 100, 200, 4, 5]
>>> list1[2:6]
[10, 20, 100, 200]
>>> list1[2:6] = []
[1, 2, 4, 5]

list1[2:3] は [3] になりますが、そこに [100, 200] を代入すると、3 が削除されて 100 と 200 が挿入されます。list1[2:2] は空リストになりますが、そこに [10, 20] を挿入すると、要素 2 の後ろに 10 と 20 が挿入されます。空リストを代入すると、要素を削除することができます。

●ディクショナリ

辞書 (ディクショナリ : dictionary) は「連想配列」のことで、Perl ではハッシュ [*4] と呼ばれています。リストが整数値を使って要素を指定するのに対し、ディクショナリはキー (key) というデータを使って要素を指定します。一般に、連想配列のキーには文字列が用いられますが、Python では変更不能なデータ型(数値、文字列、タプル)であれば、キーとして使用することができます。

ディクショナリは中カッコ '{' と '}' で囲み、要素をカンマで区切って表します。要素は「キー: データ」で指定します。{ } は空のディクショナリを表します。

簡単な例を示します。

>>> d = {'foo': 10, 'bar': 20}
>>> d['foo']
10
>>> d['foo'] = 100
>>> d['foo']
100
>>> d['baz'] = 30
>>> d
{'baz': 30, 'foo': 100, 'bar': 20}

ディクショナリのアクセスはリストと同様に角カッコ [ ] を使います。ディクショナリを生成して変数 d にセットします。d['foo'] でキー 'foo' のデータを取り出したり、そこにデータを代入すれば、d['foo'] の値を書き換えることができます。また、新しいキー 'baz' を追加する場合は、d['baz'] に値を代入すると、ディクショナリに 'baz' とその値が追加されます。

このほかにも、Python にはディクショナリを操作する関数やメソッドが用意されています。表 4 に主な関数とメソッドを示します。

表 4 : ディクショナリの操作
名前機能
dict() ディクショナリを生成する
del D[key] キーと値を削除する
len(D) ディクショナリの要素数を返す
D.clear() ディクショナリを空にする
D.keys() ディクショナリ内のキーをリストにして返す
D.values() ディクショナリ内の値をリストにして返す
D.items() ディクショナリ内のキーと値を連想リストにして返す
D1.update(D2)ディクショナリ D1 に D2 の要素を追加する

D はディクショナリを表します。簡単な使用例を示しましょう。

>>> d1 = dict()
>>> d1
{}
>>> d2 = dict([('foo', 10), ('bar', 20), ('baz', 30)])
>>> d2
{'baz': 30, 'foo': 10, 'bar': 20}
>>> d1.update(d2)
>>> d1
{'bar': 20, 'foo': 10, 'baz': 30}
>>> d1.update([('abc', 40)])
>>> d1
{'bar': 20, 'foo': 10, 'baz': 30, 'abc': 40}
>>> len(d1)
4

関数 dict() はディクショナリを生成します。dict() は引数がないと空のディクショナリを返します。キーと値をタプルにセットし、それを要素とするリストを引数に渡すこともできます。このようなリストを連想リスト (association list) といいます。

メソッド update() はディクショナリ D2 の要素をディクショナリ D1 に追加します。要素の追加はディクショナリだけではなく、連想リストを渡すこともできます。関数 len() を使うとディクショナリに登録されている要素数を求めることができます。

>>> d1.keys()
['bar, 'foo', 'baz', 'abc']
>>> d1.values()
[20, 10, 30, 40]
>>> d1.items()
[('bar, 20), ('foo', 10), ('baz', 30), ('abc', 40)]

keys(), values(), items() は、辞書に登録された順番でデータを取り出すわけではありません。取り出される順番は、辞書の実装方法によって左右されます。ご注意ください。

-- note --------
[*4] Perl で連想配列をハッシュと呼ぶのは、連想配列を実現するアルゴリズムに「ハッシュ法 (hashing) 」が用いられているからです。Python のディクショナリもハッシュ法を使って実装されています。

●セット

セット (set) はリストやディクショナリのように要素を格納するデータ型です。複数の要素を格納するデータ型を「コレクション (collection) 」とか「コンテナ (container) 」と呼びます。これまでに説明したリスト、タプル、文字列、ディクショナリがコレクションになります。セットもコレクションですが、リストと違って要素に順番はなく、重複した要素を含まないところが特徴です。

セットはデータの集合を表すのに便利なデータ型です。集合は要素の順番に意味はありません。たとえば集合 {1, 3, 5, 7} は {7, 5, 3, 1} や {5, 3, 1, 7} と表すこともできます。このように、要素は適当に並べてもかまわないのですが、ある規則で要素を整列させておく場合もあります。

セットの基本的な操作関数とメソッドを表 5 に示します。

表 5 : セットの基本操作
名前機能
set() セットを生成する
len(S) セットの要素数を返す
S.add(x) 要素 x を追加する
S.remove(x) 要素 x を削除する
S.clear() セットを空にする
S.update(xs)コレクション xs の要素を追加する

S はセットを表します。簡単な例を示しましょう。

>>> a = set([1, 2, 3])
>>> a
set([1, 2, 3])
>>> b = [1, 2, 3, 1, 2]
>>> c = set( b )
>>> c
set([1, 2, 3])
>>> d = {'abc':10, 'def':20, 'ghi':30}
>>> e = set( d )
>>> e
set(['abc', 'ghi', 'def'])
>>> len(e)
3

set() の引数にコレクションを渡すと、その要素をセットに格納します。このとき、重複した要素は取り除かれ、ユニークな要素だけがセットに格納されます。ディクショナリを渡すと、キーがセットに格納されます。また、関数 len() を使うとセットに格納されている要素数を求めることができます。

要素の追加と削除はメソッド add() と remove() を使います。メソッド clear() はセットを空にします。コレクションの要素をまとめて追加したい場合はメソッド update() を使います。簡単な例を示します。

>>> a = set()
>>> a
set([])
>>> a.add(1)
>>> a.add(2)
>>> a
set([1, 2])
>>> a.remove(1)
set([2])
>>> a.clear()
>>> a
set([])
>>> a.update([1, 2, 3])
>>> a
set([1, 2, 3])

セットは集合を扱うメソッドや演算子が用意されています。主なメソッドを表 6 に示します。

表 6 : セットの集合演算
メソッド機能
s1.issubset(s2)s1 が s2 の部分集合であれば真を返す
s1.issuperset(s2)s2 が s1 の部分集合であれば真を返す
s1.intersection(s2)s1 と s2 の積を求める (s1 & s2)
s1.union(s2) s1 と s2 の和を求める (s1 | s2)
s1.difference(s2) s2 に現れない s1 の要素を求める (s1 - s2)
s1.symmetric_difference(s2)s1 と s2 の両方にちょうど 1 つだけ現れる要素を求める (s1 ^ s2)

簡単な例を示しましょう。

>>> a = set([1, 2, 3, 4])
>>> b = set([1, 2, 5, 6])
>>> a | b
set([1, 2, 3, 4, 5, 6])
>>> a & b
set([1, 2])
>>> a - b
set([3, 4])
>>> b - a
set([5, 6])
>>> a ^ b
set([3, 4, 5, 6])
>>> c = set([3, 4])
>>> c.issubset(a)
True
>>> c.issubset(b)
False

セットにはリストのタプルのように更新不能な frozenset が用意されています。frozenset の場合、セットを更新するメソッド add(), remove(), clear(), update() は使うことができません。

●Python の制御構造

Python の制御構造はとてもシンプルで、プログラムの実行を制御する基本的な操作は、if 文、while 文、for 文の 3 種類しかありません。最初に if 文から説明します。

●if 文

if 文は「条件分岐」を行います。簡単にいうと「もしも~~ならば○○をせよ」という動作です。図 1 を見てください。

        ↓                        ↓
  ┌─────┐No          ┌─────┐No
  │  条  件  │─┐        │  条  件  │─────┐
  └─────┘  │        └─────┘          │
        ↓Yes     │              ↓Yes             ↓
  ┌─────┐  │        ┌─────┐    ┌─────┐
  │  処理A  │  │        │  処理A  │    │  処理B  │
  └─────┘  │        └─────┘    └─────┘
        │        │              │                │
        ├←───┘              ├←───────┘
        ↓                        ↓

       (1)                        (2)

               図 1 : if 文の動作

図 1 (1) では、「もしも条件を満たすならば、処理 A を実行する」となります。この場合、条件が成立しない場合は何も処理を実行しませんが、図 1 (2) のように、条件が成立しない場合でも処理を実行させることができます。(2) の場合では、「もしも条件を満たすならば、処理 A を実行し、そうでなければ処理 B を実行する」となります。すなわち、条件によって処理 A か処理 B のどちらかが実行されることになります。

一般に、プログラミング言語では、条件が成立することを「真 (true)」といい、条件が不成立のことを「偽 (false) 」といいます。実際のプログラムでは真偽を表すデータが必要になります。

Python では数値 0 や 0.0 は偽を表し、それ以外の数値は真となります。文字列の場合、空文字列 '' は偽を表し、それ以外の文字列は真と判断されます。また、空のコレクション、[], (), {}, set([]) や None というデータ型も偽を表します。新しいバージョンの Python では、真偽を表すデータ型 boolean が用意されていて、True と False で真と偽を表します。

図 2 に if 文の構文を示します。

# coding: utf-8
#
# if test: then節 else: else節
#
if test:
    処理A
    処理B
    処理C
else:
    処理D
    処理E
    処理F

図 2 : if の構文 (1)

Python は Perl と同様に # から改行までが注釈文(コメント)になります。プログラムに日本語を使う場合は、ファイルの最初に文字コード方式 (coding:) に utf-8 または shift_jis, euc-jp, iso-2022-jp などを指定します。

if のあとに条件部 test を書き、その後ろにコロンをつけます。このあとインデントを行って、真のときに実行する処理を書きます。処理は一つだけではなく、複数の処理を記述することができます。複数の処理をまとめたものをブロック (block) といいます。ブロックは定義された処理を順番に実行します。なお、条件部が真のときに実行されるブロックを then 節、偽のときに実行されるブロックを else 節と呼ぶ場合があります。

Python はインデントが等しい処理を同じブロックとして扱います。インデントが変化した時点でブロックの定義は終了します。図 2 では 4 文字でインデントを行っていて、処理 A から処理 C は同じインデントなので、同じブロックとして扱われます。したがって、test が真の場合は処理 A から C までを実行し、else 節の処理 D から F は実行されません。

test の結果が偽であれば、else 節に記述されている処理 D から F までを順番に実行します。else の後ろにもコロンをつけることを忘れないでください。なお、else 節は省略することができます。

if 文は図 3 と図 4 のように入れ子(ネスト)にすることができます。

#
# if の入れ子
#
if test_a:
    処理A
else:
    if test_b:
        処理B
    else:
        処理C

図 3 : if 文の入れ子
        ↓
  ┌─────┐No
  │  test_a  │─────┐
  └─────┘          │
        ↓Yes             ↓
        │          ┌─────┐No
        │          │  test_b  │─────┐
        │          └─────┘          │
        │                ↓Yes             ↓
  ┌─────┐    ┌─────┐    ┌─────┐
  │  処理A  │    │  処理B  │    │  処理C  │
  └─────┘    └─────┘    └─────┘
        │                │                │
        ↓                ↓                ↓
        ├────────┴────────┘
        ↓

           図 4 : if 文の入れ子の動作

test_a が偽の場合は else 節を実行します。else 節は if 文なので、条件 test_b を実行します。この結果が真であれば処理 B を実行します。そうでなければ、else 節の処理 C を実行します。この処理は図 5 のように書き換えることができます。

#
# if - elif - else
#
if test_a:
    処理A
elif test_b:
    処理B
else:
    処理C

図 5 : if の構文 (2)

C言語は eles if を使いますが、Python では elif を使って if 文を連結することができます。test_a が偽の場合は、次の elif の条件 test_b を実行します。この結果が真であれば処理 B を実行します。そうでなければ、else 節の処理 C を実行します。なお、elif はいくつでも繋げることができます。

●比較演算子と論理演算子

Python には表 7 に示す比較演算子が用意されています。

表 7 : 比較演算子
演算子意味
== 等しい
!= , <> 等しくない
< より小さい
> より大きい
<= より小さいか等しい
>= より大きいか等しい

C言語の比較演算子とほぼ同じですが、Python は != のかわりに <> を使うことができます。これらの比較演算子は数値だけではなく、文字列や他のデータ型にも用いることができます。また、C言語とは違って、x < y < z のように比較演算子をつなげて書くことができます。

簡単な例を示しましょう。

>>> 1 < 2
True
>>> 1 <= 1 < 2
True
>>> "abc" > "def"
False
>>> "abc" < "def" < "ghi"
True
>>> [1, 2, 3] > [1, 2, 4]
False

Python には表 8 に示す論理演算子があります。

表 8 : 論理演算子
操作意味
not x x の否定(真偽の反転)
x and y x が真かつ y が真ならば真
x or y x が真まはた y が真ならば真

簡単な使用例を示しましょう。

>>> not True
False
>>> not False
True
>>> True and True
True
>>> True and False
False
>>> False or True
True
>>> False or False
False

and は、左項が偽ならば右項を評価せずに偽を返します。or は左項が真ならば右項を評価せずに真を返します。

●in と not in

演算子 in と not in はコレクションの中に要素が含まれているか調べる演算子です。in は要素 x がコレクションに含まれていれば True を返し、そうでなければ False を返します。逆に、not in は要素 x がコレクションに含まれていなければ True を返し、そうでなければ False を返します。

簡単な例を示しましょう。

>>> 5 in [1, 2, 3, 4, 5]
True
>>> 10 in [1, 2, 3, 4, 5]
False
>>> 5 not in [1, 2, 3, 4, 5]
False
>>> 10 not in [1, 2, 3, 4, 5]
True

ディクショナリの場合はキーの有無を調べます。

>>> dic = { 'foo': 10, 'bar': 20 }
>>> 'foo' in d
True
>>> 'baz' in d
False
>>> 'foo' not in d
False
>>> 'baz' not in d
True

●while 文による繰り返し

繰り返しは同じ処理を何度も実行することです。まずは簡単な繰り返しから紹介しましょう。while 文は条件が真のあいだ、ブロックに書かれている処理を繰り返し実行します。

#
# while test: block
#
while test:
    処理A
    処理B
    処理C
else:
    処理Z

図 6 : while 文の構文
                      ↓
                      ├←─────┐
          False ┌─────┐      │
        ┌───│  条件部  │      │
        │      └─────┘      │
        │            ↓True        │
        │      ┌─────┐      │
        │      │  処理A  │      │
        │      └─────┘      │
        │            ↓            │
        │      ┌─────┐      │
        │      │  処理B  │      │
        │      └─────┘      │
        │            ↓            │
        │      ┌─────┐      │
        │      │  処理C  │      │
        ↓      └─────┘      │
  ┌─────┐      │            │
  │  処理Z  │      │            │
  └─────┘      ↓            │
        │            └──────┘
        └──────┐
                      ↓

             図 7 : while 文の動作

図 6, 7 を見ればおわかりのように、while 文はいたって単純です。C言語とは違い、Python の while 文は else 節を定義することができます。else 節は while ループが終了したあとに実行されます。

簡単な例を示しましょう。hello, world を 10 回表示するプログラムをリスト 1 に示します。

リスト 1 : hello. wolrd の表示

n = 0
while n < 10:
    print 'hello, world'
    n += 1

変数 n を 0 に初期化し、n の値が 10 よりも小さいあいだ処理を繰り返します。C言語と同様に、n += i は n = n + i と同じ意味です。このほかに、-=, *=, /= も使うことができます。n の値はブロックを実行するたびに +1 されていくので、n が 10 になった時点で繰り返しを終了します。

●for 文による繰り返し

Python にはもう一つ繰り返しを行う for 文があります。for 文はコレクションから順番に要素 (ディクショナリの場合はキー) を取り出して変数に代入し、ブロックに書かれている処理を繰り返し実行します。Python の for 文は Perl の foreach と同じです。C言語の for 文とは違うことに注意してください。for 文の構文を図 8 に、動作を図 9 に示します。

#
# for var in collection:
#     block
#
for 変数名 in コレクション:
    処理A
    処理B
    処理C
else:
    処理Z

図 8 : for文 の構文
                      ↓
                      ├←────┐
           False┌─────┐    │
        ┌───│要素がある│    │
        │      └─────┘    │
        │            ↓True      │
        │      ┌─────┐    │
        │      │変数←要素│    │
        │      └─────┘    │
        │            ↓          │
        │      ┌─────┐    │
        │      │  処理A  │    │
        │      └─────┘    │
        │            ↓          │
        │      ┌─────┐    │
        │      │  処理B  │    │
        │      └─────┘    │
        ↓            ↓          │
  ┌─────┐┌─────┐    │
  │  処理Z  ││  処理C  │    │
  └─────┘└─────┘    │
        │            └─────┘
        └──────┐
                      ↓

              図 9 : for 文の動作

for 文の構文は、for と in の間にコレクションの要素を格納する変数を指定し、in の後ろにコレクションを指定します。このあと、コロンを書いてインデントでブロックの範囲を指定します。また、for 文は while 文と同様に else 節を定義することができます。簡単な例を示しましょう。

>>> a = [1, 2, 3]
>>> for x in a:
        print x

1
2
3
>>> d = {'foo': 10, 'bar': 20, 'baz': 30}
>>> for x in d:
        print x

baz
foo
bar

シーケンスの場合、for 文は先頭から順番に要素を取り出します。ディクショナリの場合、キーを取り出す順番はディクショナリの実装方法に依存します。アルファベット順に取り出していくわけではありません。

for 文で使用する変数は、タプルで複数個指定することができます。簡単な例を示します。

>>> for a, b in [[1, 2], [3, 4], [5, 6]]:
        print a * b

2
12
30

リストの要素数が変数の個数と一致しないとエラーになります。ご注意ください。

●繰り返しの制御

while 文や for 文は break 文によって繰り返しを脱出することができます。この場合、else 節が定義されていも実行されません。contiune 文は繰り返しの先頭に戻ります。break 文と continue 文の動作を図 10 に示します。

#
# break と continue
#
while test_a: ←──────┐
    処理A                   │
    if test_b: continue ──┘
    処理B
    if test_c: break ───┐
    処理C                  │
else:                      │
    処理D                  │
 ←────────────┘
処理E

図 10 : break 文と continue 文の動作

test_b が真で continue 文が実行されると、それ以降の処理を実行せずに条件部のチェックが行われます。つまり、処理 B, test_c, 処理 C は実行されません。for 文で continue 文が実行されると、それ以降の処理は実行されずに次の要素を取り出す処理が行われます。

test_c が真で break 文が実行されると、それ以降の処理を実行せずに while 文や for 文の繰り返しを脱出します。このとき、else 節が定義されていても実行されません。図 10 では、break 文で while 文の繰り返しを脱出すると、while 文の次の処理 E が実行されます。else 節の処理 D は実行されないことに注意してください。

●range() によるリストの生成

for 文を使う場合、要素が数値のリストを生成する関数 range() を使うと便利です。

range(end)
range(start, end)
range(start, end, step)

関数 range() の引数 start と end はスライス操作と同じ指定方法です。引数が一つで start が省略された場合、リストの要素は 0 から始まり、値を +1 しながら end - 1 までの数値を生成します。引数が 2 つの場合は start から end - 1 までの数値を生成します。引数が 3 つの場合は、start から end 未満までの数値を step 分加算しながら生成します。

簡単な例を示します。

>>> range(8)
[0, 1, 2, 3, 4, 5, 6, 7]
>>> range(2, 8)
[2, 3, 4, 5, 6, 7]
>>> range(10, 100, 20)
[10, 30, 50, 70, 90]

range() を使うと、hello, world を 10 回表示するプログラムは、リスト 2 のようになります。

リスト 2 : hello, world の表示

for i in range(10):
    print 'hello, world'

while 文を使うよりも簡単です。1 から 1000 までを加算するプログラムはリスト 3 のようになります。

リスト 3 : 1 から 1000 までの合計値

total = 0
for i in range(1, 1001):
    total += i
print total

変数 i には 1 から 1000 までの数が順番にセットされ、変数 total に加算されます。答えは 500500 になります。

●リストの内包表現

Ptyhon はリストの中に for 文を書いて、リストを生成することができます。これを「リストの内包表現」といいます。基本的な構文を次に示します。

[式 for 変数, ... in コレクション]

最初に要素の値を計算する式を書き、次に for 文を書きます。この後ろに for 文または if 文を続けることができます。簡単な例を示します。

>>> list1 = [1, 2, 3, 4, 5]
>>> [x * x for x in list1]
[1, 4, 9, 16, 25]
>>> [(x, x * x) for x in list1]
[(1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
>>> [x * x for x in list1 if x % 2 == 0]
[4, 16]
>>> [x + y for x in range(3) for y in range(10, 13)]
[10, 11, 12, 11, 12, 13, 12, 13, 14]

for 文の後ろに if 文を続けると、条件部が真のときに式を評価してリストを生成します。上の例では、x が偶数のときに式が評価されて要素 4 と 16 のリストが生成されます。for 文の後ろに for 文を続けると二重ループになります。上の例では、リストには 9 個の要素が格納されます。

●for 文と組み合わせて使うと便利な関数

range() のほかにも、for 文は関数 enumerate(), zip(), メソッド iteritems() と組み合わせて使うと便利です。

関数 enumerate() は、要素の位置が必要なときに使うと便利です。

>>> for n, m in enumerate(['abc', 'def', 'ghi']):
        print n, m


0 abc
1 def
2 ghi

print で複数のデータを表示する場合は、引数をカンマで区切ります。データとデータの間には空白が挿入されます。

最初の変数 n に要素の位置(添え字)がセットされ、2 番目の変数 m に要素がセットされます。これはリスト 4 に示す処理と同じです。

リスト 4 : enumerate と同じ処理

n = 0
for m in ['abc', 'def', 'ghi']:
    print n, m
    n += 1

変数 n を 0 に初期化する処理と 1 を加算する処理が不要になる分だけ、enumerate() を使ったほうが簡単になります。

iteritems() はディクショナリのメソッドで、キーと値を同時に取り出すことができます。

>>> dic1 = {'foo':10, 'bar':20, 'baz':30 }
>>> for key, value in dic1.iteritems():
        print key, value


bar 20
foo 10
bar 30

最初の変数 key にディクショナリのキーがセットされ、2 番目の変数 value に値がセットされます。メソッド items() はキーと値をタプルに格納したリストを生成して返しますが、iteritems() はリストを生成しないので効率的です。

zip() は引数に複数のリストを受け取り、各リストの要素をタプルに詰め込み、それをリストに格納して返します。複数のリストを操作する場合、zip() はとても便利です。

>>> zip(['a', 'b', 'c'], [1, 2, 3])
[('a', 1), ('b', 2), ('c', 3)]
>>> for x, y in zip([1, 2, 3]. [10, 20, 30]):
        print x + y


11
22
33

●素数を求める

最後に簡単な例題として、素数を求めるプログラムを作ってみましょう。いちばん簡単な方法は、奇数 3, 5, 7, 9, ...をそれまでに見つかった素数で割ってみることです。見つかった素数はリストに格納しておけばいいでしょう。プログラムをリスト 5 に示します。

リスト 5 : 素数を求める(1)

prime_list = [2]

for x in range(3, 100, 2):
    for y in prime_list:
        if x % y == 0: break
    else:
        prime_list.append(x)

print prime_list

変数 prime_list は素数のリストで [2] に初期化します。奇数の生成は range を使うと簡単です。最初の for 文で奇数を取り出して変数 x にセットします。次の for 文で prime_list から素数を取り出して変数 y にセットします。

x % y が 0 であれば、x は素数 y で割り切れたので x は素数ではありません。break 文で for ループを脱出します。このとき else 節は実行されないので、x が prime_list に追加されることはありません。

for が最後まで終了すれば x は素数です。この場合は else 節が実行されるので、素数 x は append で prime_list に追加されます。最後 に print で prime_list を表示します。

それでは実行してみましょう。プログラムを prime.py に保存して、シェルで python prime.py を実行してください。

C>python prime.py
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 
53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

100 以下の素数は全部で 25 個あります。

ところで、この方法には無駄があります。x が素数か判別するため、x より小さい素数で割り切れるか調べていますが、実は√x より小さい素数を調べるだけでいいのです。リスト 5 をむりやり改造すると、リスト 6 のようになります。

リスト 6 : 素数を求める(2)

prime_list = [2]

for x in range(3, 100, 2):
    a = False
    for y in prime_list:
        if y * y > x:
            a = True
            break
        if x % y == 0: break
    if a:
        prime_list.append(x)

print prime_list

変数 a の使い方がポイントです。x が素数の場合は a をTrue にセットします。最初に a を False に初期化しておきます。y > √y のかわりに y * y > x をチェックし、真であれば a に True をセットして break します。x % y が 0 ならば、a は False のままで break します。そして、for ループが終了した後、変数 a をチェックして True であれば x を prime_list に追加します。

これでリスト 5 よりも高速に素数を求めることができますが、リスト 6 のプログラムはちょっとわかりにくいのが欠点です。この場合、関数を使うとわかりやすいプログラムを作ることができます。関数は次回で詳しく説明します。

●おわりに

Python の基本的なデータ型とデータ構造と制御構造について説明しました。Python はオブジェクト指向言語ですが、無理にオブジェクト指向機能を使わなくても、いろいろなプログラムを作ることができます。特に Python の関数は柔軟性があり、関数を使いこなすとちょっと複雑なプログラムでも簡単に作ることができます。次回は関数とファイル入出力について説明します。


Copyright (C) 2006 Makoto Hiroi
All rights reserved.

[ PrevPage | Python | NextPage ]