PYTHON勉強会
第三回Python勉強会
公開日:
2020/05/17
第三回Python勉強会

はじめに

今回紹介する制御文とループさえ使う事が出来れば最低限のプログラムは書けるようになります。

制御文

if文です。他の言語を学んだ事がある方はおなじみのやつです。

>>> x = 10 # 自分の好きな数字を入れる
>>> if x < 0:
...   print('Negative Number')
... elif x == 0:
...   print('Zero')
... else:
...   print('Positive Number)
...
Positive Number

print('ABCDE')でABCDEを表示する事が出来ます。なんとなくやっている事は理解できるのでは無いでしょうか。以下の様な形になりますね。

if 条件:
(インデント)処理
elif 条件:
(インデント)処理
else:
(インデント)処理
(空行)

elifはelse ifの略で、それより上の条件(今回はx < 0)を満たさない時、かつelifの条件を満たす時に処理が実行されます。elseはそれ以外の時実行です。

elifは複数個あってもいいし、無くても構いません。elseも絶対に必要という訳では無いです。あると便利な時に使えばいいです。

注意点が複数。

  1. 処理の部分には複数行のコードを書く事が出来ます。その際インデントをそろえる必要があります。ここからここまでが処理の塊という事を明記するためにインデントが必要という事です。
  2. 最後の空行は必要でない時が存在します。例えばif文の処理の中にif文が入る時、内部のifで空文を打つと、それは外側のif文の終了を表す事になってしまうのです。空文は0インデントを表します。インデントの途中ならばインデントの深さを調整すればいいだけです。言葉だけでは伝わらないので例を上げます。
>>> x = 10
>>> if x > 0:
...   x -= 100
...   if x < 0:
...     x = 0
...     x += 20 # ここまで内側if
...   x += 1
...

別に意味のある処理はしていません。こういうふうにインデントを書くのかと見てもらえば。

if文の中の条件として使える代表的なものを列挙しておきます。

記号 trueになる条件
a < b aはb未満
a <= b aはb以下
a > b bはa未満
a >= b bはa以下
a == b aとbは等しい
a != b aとbは異なる

等しいかの判定条件でa = bと書かない様に注意して下さい。これはaにbを代入となりエラーとなります。(Pythonだとエラーとなるのでよいですが、C系の言語の場合エラーを吐かないので注意です。高速化や短さのためにあえてそのような書き方をする人もいるので...)

さて、練習しましょう。復習の意味も含めて前回習った関数として作って下さい。

例) xを受け取り、xの絶対値を返すabs関数を作って下さい。できれば下を見ずに!

>>> def abs(x):
...   if x < 0:
...     return -x
...   else:
...     return x
... 

list型

Pythonにおいてlist型は全ての基本なので(説明する場所としては微妙なのですが)ここで説明しようと思います。リストは列を作るデータ構造です。(上級者向けの説明: データ構造として有名なリストというよりはCの配列に近いです。)コードを見る方が分かりやすいでしょう。

>>> d = [1, 2, 3, 4, 5]
>>> d
[1, 2, 3, 4, 5]
>>> d[0]
1
>>> d[3]
4
>>> d[1, 3]
[2, 3]
>>> d[1] = 10
>>> d
[1, 10, 3, 4, 5]
>>> d + [2, 3]
[1, 10, 3, 4, 5, 2, 3]
>>> d.append(10)
>>> d
[1, 10, 3, 4, 5, 10]

1行目でlistを定義しています。このように[]で囲んで,区切りで書きます。listのi番目にはd[i]でアクセスできます。値の書き換えも可能です。+演算子でlistを結合する事も出来、appendで一番最後の要素に追加も出来ます。

[a:b]と書いた時、リストのa番目からb-1番目までのリストを取り出している事に注意して下さい。つまり、[a, b)の範囲という事です。プログラミングでは半開区間を使う事が多いです。また、一番最初の要素は0番目です。最初は慣れないかもしれませんが、実はかなり便利です。ちなみにaを省略すると0, bを省略するとリストの要素数が入っているものとみなされます。

>>> d = [1, 2, 3, 4, 5]
>>> d[3:]
[4, 5]
>>> d[:2]
[1, 2]
>>> d[:3] + d[3:] # 半開区間だと区間の分割が楽
[1, 2, 3, 4, 5]

Pythonは動的型付け言語で、簡単に言うと型が緩いです。Cなどの静的型付け言語では整数の配列を宣言するとそこに実数を代入する事は出来ないのですが、Pythonではlistの中に違う型のものを入れる事も可能です。

>>> d = [1, 2.2, [3, 4]]
>>> d[0]
1
>>> d[1]
2.2
>>> d[2]
[3, 4]
>>> d[2][0]
3
>>> d[2][1]
4

listの中にlistを入れる事も簡単に出来ます。

違う型のlistが作れるメリットは他言語で構造体に相当するものを簡単に作ることができる事です。例えばとてもてきとうな例を挙げるとRPGで[HP(整数), MP(整数), x座標(小数), y座標(小数)]みたいにlistを作って主人公のステータスを表現するとか。しかし、これは1番目の要素が何を表しているのか人間が見て分かりづらいので避けるべきです。後で出てくるclassを使うのが良いでしょう。違う型のlistはclassを作る程でもない時に使うと良いです。

listが同じ型のみで構成されている時のメリットは再帰的な処理をかけやすい事です。例えば整数だけのlistなら2倍した値のlistを返すとか。(厳密に言うとlist in listも再帰的なデータ構造になるのでそこまで扱いづらいわけでは無いのですがね...)この話はここで止めておきます。

for文

for文は繰り返しのための構文ですが、C言語のfor文とは異なります。他言語のforeachに近いですね。例を見てみましょう。

>>> for i in range(5):
...   print(i)
...
0
1
2
3
4
>>> for i in range(2, 5):
...   print(i)
...
2
3
4
>>> for i in range(0, 10, 3):
...   print(i)
...
0
3
6
9

range関数が1つの引数を取る時、for i in range(n)でi=0, 1, 2, ..., n-1の順番にn回ループが実行されます。これも半開区間です。

range関数が2つの引数を取る時、for i in range(a, b)でi=a, ..., b-1のb-a回ループが実行されます。

range()関数が3つ引数を取る時、for i in range(a, b, c)でi=a, a+c, a+2c, ..., (b未満でa+xcとなる最大の整数)のループが実行されます。

実はinの後にlistを入れるとlistの中身が順番にループで回ります。

>>> d = [1, 3, 4, 9]
>>> for i in d:
...   print(i)
...
1
3
4
9

つまり、range関数はlistを作る関数で、for文はlistを走査する構文だ、のように大雑把に解釈してくれて構いません。大雑把 と付けたのは、厳密にはrange関数はlistを生成していないからです。これは効率の為です。rangeでlistを作りたい時は以下の様にlist()関数で囲いましょう。

>>> range(0, 5)
range(0, 5)
>>> list(range(0, 5))
[0, 1, 2, 3, 4]

また、他言語でもおなじみのbreakとcontinueも存在します。breakはループを途中で抜けたい時に、continueは今のループを止めるが、ループは続行したい時に使います。

>>> for i in range(8):
...   if (i == 3):
...     break
...   print(i)
... 
0
1
2
>>> for i in range(8):
...   if (i == 3):
...     continue
...   print(i)
... 
0
1
2
4
5
6
7

実行結果を見れば分かると思います。breakの時はそこでfor文を終了するのですが、continueの時i=4以降の処理は実行されていますね。

while文

英語の意味のまんまです。

>>> i = 0
>>> while i < 10:
...   print(i)
...   i += 1
... 
0
1
2
3
4
5
6
7
8
9

whileの後の条件が成立する間ループが実行されます。無限ループを作りたい時は

>>> while True:
...   print("Hello World")
...

と書けば良いです。これを実行してしまった人はCtrlキー + Cで強制終了させましょう。ループ終了条件が複雑な時に無限ループを作る事があります。(ちゃんとbreakを書いて終了させましょうね)while文もbreak, continueは使えます。

ここで注意なのですが、while文は手続き型が強くなるので可能な限りwhileは避けてfor文で書くべきです。理由は上の例でiの初期値が何かがwhile文の中だけを見て分からないからです。今回は上にi=0と代入式が書かれているので分かりやすいですが、もし複雑な事をしようとするとiがどういう動きをするのか把握するのが困難になります。

別な言い方をするとiがwhile文内部で完結しておらず、モジュール化の観点で微妙だからです。

練習問題

  1. for文を使って100未満の素数を列挙して下さい。
  2. 引数が素数かどうかを判定するis_prime関数を作って下さい。(素数の場合はreturn True/そうでない場合はreturn Falseと書きましょう)
  3. 2で作った関数を用いて1をもう一度解いてみましょう。(ifの条件に関数を入れる, True/Falseの説明をハニワがする)
  4. 引数が平方数(√とって整数になる数)かを判定する関数を作って下さい。
  5. 引数が負の数なら0を、100以上なら100を、50以上なら-50した数を、それ以外ならその数を返す関数を作って下さい。
    warning
    ここからは余力のある人だけで大丈夫です。 {{< /alert >}}
  6. 2, 4で引数がnの時、だいたい何回程度実行されるか考察してみましょう。
  7. 恐らくnに比例する回数ループが実行されるコードを書いているかと思います。より高速に実行する手法を考えてみましょう。2, 4共に√nに比例するコードは簡単に書けます。4はより工夫するとlog nに比例するコードも書けます。もっと高速な解法もあります(ヒント: ニュートン法)。
  8. 2, 4に対して√nに比例する回数のループで終了する関数を別に作ってみましょう。
  9. それぞれ10^12くらいの数を元の関数、新たに作った関数に入れてみて比較してみましょう(強制終了はCtrl + C)

(ここでハニワ君がなんかいい感じの言葉を言って総括する)

loading...