1 準備と講義概要
教員解説を聞きながら「一斉進行形式」で学びたい学生は 教室前方の教卓付近 に座ってください。講義資料を読みながら各自のペースで学び進めたい学生は最後列を含めて自由に座ってください。
GoogleColab にログインしておいてください。
PG1-第06回講義.ipynbという名前で「GoogleColabノートブック」を作成しておいてください。今回はノートブックの提出はありません。
今回の講義では 条件分岐構文 について学びます。
- Colabのフォーム機能、テキストセルに数式を記述する方法も学びます。
課題02について忘れずに取り組み、提出してください。
次回講義で「小テスト❷」を実施します。
2 前回の復習 ( 12分)
繰返し構文 (for 構文) と
ColabTurtle
ライブラリを使用して、次のような六角形を描画してください。コードセルの実行には
Ctrl + Enter
のショートカットを利用する習慣をつけてください。
%reset -f
import ColabTurtle.Turtle as t
t.initializeTurtle(initial_speed=13,initial_window_size=(400,400))
t.shape(shape='circle') # ペン先を「亀」から「円」に設定
t.bgcolor(0,0,0); # 背景色を「黒」に設定 bg:background
t.color(0,255,0) # 線色を「緑」に設定
t.width(10) # ペンの太さを「10」に設定
# ▼▼▼ 以降を書き替える ▼▼▼
t.up() # ペンを上げる
t.goto(50,350) # X=50, Y=350 に移動
t.face(0) # 0度方向 (3時方向) を向く
t.down() # ペンを下げる
for i in range(3): # 3回の繰返し
t.forward(50) # 50px 前進
t.left(90) # 90度の右回転- ヒント :
ColabTurtleライブラリは GoogleColab に標準インストールされていません。ColabTurtleライブラリを使うためには、あらかじめpipコマンド を使ってライブラリをインストールする必要がありました。 - ヒント :
ColabTurtleでは、3時方向が「0度」、6時方向が「90度」、12時方向が -90度 になります。また、以下の2つの違いを正しく理解してください。t.face(90)は、カメ (カーソル) を90度方向に向ける。t.left(90)は、カメ (カーソル) を現在の向きから90度だけ左に回転する。
3 課題02に関する補足
前回講義で出題した課題02に関連する補足です。
3.1 ColabTurtleのカメの移動速度
複雑な図形を描く場合は、カメ(カーソル)の移動速度の初期値
(initial_speed) を最大値である
13 にすると短時間で描画処理が終了します。開発中は
13 に設定することをお勧めします。
import ColabTurtle.Turtle as t
t.initializeTurtle(initial_speed=13,initial_window_size=(400,400)) # 速度設定3.2 繰返し回数を「整数値」で与えるためのTips
for i in range(10):
のような構文で繰返し処理をする場合、range
に与える引数は 整数
にしないと実行時エラーが発生します。以下のコードで実際に確認してみましょう
(以下では range の引数 (=繰り返し回数) を整数ではなく
実数 で与えています) 。
実行すると Type Error(型の誤り) が発生します。
図形処理では range
の引数を「数式」で与えたい場合がありますが
(例えば360/n
のようなケース)、このような場合、実行時エラーを回避するためには次のような工夫をします。
また、目的に応じて range(360//n+1)
のように繰返し回数を調整します。なお、慣れないうちは、適宜、括弧を使って
range((360//n)+1)
のように記述すると分かりやすいかもしれません。
//演算子は 第03回講義 で既に学習済みです。int関数は 第05回講義 で既に学習済みです。int関数は「文字列」を「整数値」にするほか、「実数値」を「整数値」にするときにも利用できます。int関数で、「実数値」を「整数値」に変換するとき、四捨五入、切り上げ、切り捨てのいずれになるかは実際に自分で確認してみてください。print(int(4.5))
4 インデントとブロック
Pythonでは、インデント (字下げ) により ブロックの範囲 を指示します。
ブロックとは C/C++言語 (Arduino言語を含む) や
JavaScript などのプログラミング言語では { と
} の記号によって与えるもので、例えば、繰返し構文や条件分岐構文の適用範囲
(どこからどこまでの範囲を繰り返すのか、条件を満たすときにどこからどこまでの範囲を実行するのか)
を指示するときになどに利用されます。
Pythonにおいて、ブロックは次のように 同じ幅を持ったインデント によって指示します。一般にインデントは 半角スペース4個 を使って表現しますが、この講義資料では可読性の観点から「半角スペース2個」をインデントに使用します。
次のプログラムを Google Colab. のノートブックに貼り付けて実行し、ブロックの内部では インデント幅を同じにしなければならない ことを確認してください。
for i in range(3):
print('AA') # 幅2
for i in range(2):
print('BBB') # 幅4
print('CCC') # 幅4
for i in range(2):
print('DDDD')
print('EEEE')
print('FFFF')- 上記プログラムの 第08~11行目の範囲を修正 して、次のような標準出力が得られるように修正せよ。
DDDD
EEEE
FFFF
DDDD
EEEE
FFFF
なお、インデントには「タブ文字」を使うこともできます。ただし、画面上の見かけの文字幅が同じであっても、「タブ文字」と「スペース」は別物なので、ブロック内で両者を混在させることはできません。
また、インデントは 全角スペース では機能しません。実際に全角スペースを使ってインデントを与え、どのようなエラーが生じるかを確認してください。
4.1 演習1 ( 8分)
次の各プログラムを実行したとき どのような出力 (実行時エラーを含む) が得られるか を予測してください(=脳内でプログラム動作をシミュレートせよ)。また、実際に Colabノートブックで実行して「予測」と「結果」が一致するか確認してください。
5 GoogleColabのテキストセルでの数式記述
Colab.のテキストセルでは マークダウン記法 で文字装飾ができることを既に紹介していますが、さらに TeX記法による数式の記述 も可能となっています(TeX は テフ と読みます)。
例えば、Colab の「テキストセル」のなかで
$$ と $$
で囲んで次のように記述すると…
$$ \sum_{k=1}^{10}(3k^{2}-1) $$
$$ \sum_{k=1}^{n}k^{2}=\frac{1}{6}n(n+1)(2n+1) $$
$$ \sum_{k=1}^{n}(a_{k}\pm b_{k})=\sum_{k=1}^{n}(a_{k})\pm \sum_{k=1}^{n}(b_{k}) $$
次のように 整形された数式が画面表示 されます。
\[ \sum_{k=1}^{10}(3k^{2}-1) \]
\[ \sum_{k=1}^{n}k^{2}=\frac{1}{6}n(n+1)(2n+1) \]
\[ \sum_{k=1}^{n}(a_{k}\pm b_{k})=\sum_{k=1}^{n}(a_{k})\pm \sum_{k=1}^{n}(b_{k}) \]
実際にコピペして確認してみてください。記法の詳細については「TeX 数式」などでキーワード検索してみてください。
なお、独立式ではなく文章中に数式を入れたい場合は、次のように
$ と $ で囲みます。
ここで
$a_{n}$は・・・・
6 Colabのフォーム機能
Google Colab の環境では「フォーム」という機能を使ってGUIライクに入力を与えることもできます。
次のコードを実行して、その動作を確認してみてください。変数に値を代入している行のコメントで
#@param ... のように書いているのがポイントです。
%reset -f
name = '山田' #@param {type:"string"}
height = 172.5 #@param {type:"number"}
age = 10 #@param {type:"slider", min:10, max:80, step:1}
print(f'{name}さんの身長は{height}で、現在年齢は{age}歳で、1年後は{age+1}歳になっています')この フォーム の機能は、GoogleColab環境でのみ使用ができます (Python固有の機能ではありません)。詳細については 公式ページ を参考にしてください (ドロップダウンリストや日付選択コンポーネントなど、様々なフォームが紹介されています)。
セルを選択して、三点リーダを選択するとフォームに関する オプション設定 ができます。
6.1 フォームの利用例
次のコードを実行して動作を確認してください。#@markdown
に続けて、数式を含めたマークダウン記法が利用できていることが分かると思います。
%reset -f
#@title **物理学習支援ツール**
#@markdown 時刻 $0$ において速度 $v$ ($\mathrm{m/s}$) の物体が、
#@markdown 一定の加速度 $a$ ($\mathrm{m/s^{2}}$) を保ちながら
#@markdown $t$ 秒間の間に進む 距離 $x$($\mathrm{m}$) を求めます。
#@markdown 速度 $v$ ($\mathrm{m/s}$) を入力してください
v = 1.5 #@param {type:"number"}
#@markdown 加速度 $a$ ($\mathrm{m/s^{2}}$) を入力してください
a = 2 #@param {type:"number"}
#@markdown 走行時間 $t$ ($\mathrm{s}$) を入力してください
t = 4 #@param {type:"number"}
x = v*t + 0.5*a*t**2
print(f't=0 から t={t} に走行した距離は {x:.2f} (m) です。')7 条件分岐構文
条件分岐構文
(通称「if文」)
は、何らかの条件に応じて処理の流れを変えたい (つまり分岐させたい)
ときに使用します。具体的には num <= 4
のような「条件式」を与えて、それが「成立するか
(真であるか)」「成立しないか
(偽であるか)」によって実行するコードを変えます。
繰返し構文と同様に 処理の範囲 (=ブロック) をインデントにより指示 します。
実例で考えてみましょう。次のプログラムは、サイコロを投げて「1~4の目がでたとき」は「はずれ」、一方で「5または6がでたとき」は「あたり」の処理をするものです。実際に実行して動作を確認してください。
%reset -f
import random
for i in range(5): # 5回チャレンジ
dice_num = random.randint(1,6) # [1,6]の範囲の乱数生成
print(f'サイコロで{dice_num}がでたので「',end='')
# 条件分岐構文
if dice_num <= 4 : # 末尾のコロン (:) を忘れがちなので注意
print('はずれ',end='')
else : # 末尾のコロン (:) を忘れがちなので注意
print('あたり',end='')
print('」です。')なお、Python言語以外、例えば C/C++言語 (Arduino言語を含む)
などでは、条件式を ( と
) で囲みますが、Python言語では囲まない
ので注意してください。
7.1 アタマを柔らかくして分岐条件を与える①
上記のプログラムは、以下のように書き換えることができます。どちらも、実質的に同じ機能を提供します。
%reset -f
import random
for i in range(5):
dice_num = random.randint(1,6)
print(f'サイコロで{dice_num}がでたので「',end='')
if dice_num >= 5 : # 5以上ならば…。記号が「>」ではなく「>=」に注意
print('あたり',end='')
else :
print('はずれ',end='')
print('」です。')プログラムは 自然言語 (日本語) で与えられた手順どおりに実装する のではなく(アタマを柔らかくして)必要に応じて手順やロジックを工夫して実装することが重要です(ときには求められます)。
7.1.1 演習2 ( 6分)
\(25\%\)の確率で「R」、\(75\%\)の確率で「N」という文字列を出力するプログラムを作成してください。次のプログラムに追記する形で作成してください。
まずは、次のプログラムについて、何も変更せずにそのまま実行して結果を確認し、その後、編集を加えてください。
%reset -f
import random as r
for i in range(15): # 15連ガチャ
n = r.random() # 0.0以上1.0未満の実数値
print(f'n={n:.3f}') # 乱数確認用(あとでコメントアウトする)注意 : random()
は、randint() とは違って、random(0, 1)
のように「引数」を与えずに使用します。もし、\(0.0\) 以上 \(20.0\) 未満の実数を得たい場合は
r.random() * 20 のようにします。また、\(-10.0\) 以上 \(のようにします。10.0\)
未満の実数を得たい場合は r.random() * 20 - 10
のようにします。
7.2 「等しい」という条件の与え方
比較演算子 には大小関係を評価する
> >= <
<= の他に、「等しい」を評価する
== が使用できます。ここで = ではなく ==
が使われることに強く注意してください。
実例で考えてみましょう。次のプログラムは、サイコロを投げて3の目がでたときだけ「あたりの処理」をするものです。実際に実行して、確認してみてください。
%reset -f
import random
dice_num = random.randint(1,6)
print(f'サイコロで{dice_num}がでました。')
if dice_num == 3: #「=」ではなく「==」であることに注意
print('やったね!!')
print('また挑戦してね。')
# ↑インデントしないことで、if文が抜けたあとの処理であることを与えているこのプログラムから分かるように、if文 (条件分岐構文) では必ずしも else節を必要としません。
なお、比較演算子の「等しい (==) 」は
数値だけではなく 文字列に対して使用できます。以下に例を示します。
# 元ネタ FC版DQ3
%reset -f
name = input('名前を入力してください。')
if name == 'ロト' :
print('その名前は使用できません。')
else :
print(f'''「おはよう、{name}。
もう あさですよ。
きょうは とても たいせつなひ。
{name} が はじめて おしろに いくひ だったでしょ。」''')以前に助言したように「教わったこと」を教わった範囲で無条件に受け入れて終わるのではなく、好奇心や興味関心を持って、発展的に「試す」「調べる」「考える」に取り組めるように なってください。
例えば、ここでは次のような「疑問」や「興味」が湧いて、それに対して「試す」「調べる」「考える」ができるようになってください。そういった習慣や思考回路になった人が、最終的に (4年生になる頃に) 高いプログラミングを身に付けることができます。
- 第07行目 の 三連引用符
'''は、第05回講義 で既に学習済みです。 - 第04行目 で
if name == 'ロト'ではなくif name = 'ロト'にすると、どうなるのか確認してください。 - 条件式のなかで計算はできるのか確認してください。例
if 8 > 2 + 3 :など。
7.3 「等しくない」という条件の与え方
「等しくない」は
!=
という比較演算子によって評価することができます。
7.4 アタマを柔らかくして分岐条件を与える②
条件を満たすときは何もせず、条件を満たさないときだけ何かをしたいという処理はどのように記述すればよいか考えてみてください。
例えば「サイコロを投げて6の目がでたときは何もせず、それ以外のときは「はずれ」を表示する」という処理を考えます。
まず、はじめに思い浮かぶのは、次のようなプログラムになると思います。実際に実行して結果を確認してください。
%reset -f
import random
dice_num = random.randint(1,6)
if dice_num == 6:
# 何も処理しない
else:
print('はずれ')実行するとエラーとなることが確認できたと思います (実行以前の段階で赤の波線が表示されていることにも気づきましたか?) 。
Pythonでは、文法上、何も処理しないブロック
(文が1つも存在しないブロック)
を構成することは禁止されています。ブロック内では、(コメント以外に)
必ず何らかの文を書く必要があります。そこで、何もしない文として
pass が存在します。
上記のプログラムは次のように書き換えることで実行可能となります。
%reset -f
import random
dice_num = random.randint(1,6)
if dice_num == 6:
pass # 何も処理しない。
else:
print('はずれ')しかし、pass
を使用しなくとも、次のように書き換えることで、より短いコードで同じ処理を実現することができます。繰返しになりますが、プログラムは
自然言語 (日本語)
で与えられた手順どおりに実装する
のではなく(アタマを柔らかくして)必要に応じて手順やロジックを工夫して実装することが重要です。
7.5 elif節
elif
は、次のような処理をしたい場合に利用します。
%reset -f
score = 85
print(f'試験が {score} 点だったので「',end='')
if score >= 90 :
print('秀',end='')
elif score >= 80 :
print('優',end='')
elif score >= 70 :
print('良',end='')
elif score >= 60 :
print('可',end='')
else :
print('不可',end='')
print(f'」の評価です。')上記のプログラム (elifを利用) と下記のプログラム
(ifを利用)
では処理の流れが変わってきます。実行時に、どのように違いがでるのかについて考えてみてください。
%reset -f
score = 85
print(f'試験が {score} 点だったので「',end='')
if score >= 90 :
print('秀',end='')
if score >= 80 :
print('優',end='')
if score >= 70 :
print('良',end='')
if score >= 60 :
print('可',end='')
else :
print('不可',end='')
print(f'」の評価です。')7.5.1 演習3 ( 10分)
15連ガチャを実装するとします。\(10\%\)の確率で「SR」、\(25\%\)の確率で「R」、\(65\%\)の確率で「N」という文字列を出力するプログラムを作成してください。次のプログラムに追記する形で作成してください。
%reset -f
import random as r
for i in range(15): # 15連ガチャ
n = r.random() # 0.0以上1.0未満の実数値
print(f'n={n:.3f}') # 乱数確認用(あとでコメントアウトする)elif節を利用するとシンプルに記述できる。
7.6 条件分岐構文のネスト
ネスト とは 入れ子 とも呼ばれるもので、条件分岐構文のなかに、さらに条件分岐構文を構成することを意味します。
基本的には何階層にも入れ子にすることができますが、深いネストを構築すると 可読性や保守性が著しく低下 します。深いネストが構成されないようにプログラムを工夫してください。
%reset -f
Ax = 5
Ay = -3
print('点Aは第',end='')
if Ay > 0 :
if Ax > 0 :
print('1',end='')
else :
print('2',end='')
else :
if Ax < 0 :
print('3',end='')
else :
print('4',end='')
print('象限に存在します。')elif 節を使うことで 深いネストが構成されることを回避すること
ができます。先ほどの「秀・優・良・可・不可」の判定プログラムを
elif
を使わずに構成すると、以下のように
深いネストが形成されてしまいます
(可読性・保守性の低いプログラムになってしまうことが分かると思います)。
%reset -f
score = 45
print(f'試験が {score} 点だったので「',end='')
if score >= 90 :
print('秀',end='')
else :
if score >= 80 :
print('優',end='')
else :
if score >= 70 :
print('良',end='')
else :
if score >= 60 :
print('可',end='')
else :
print('不可',end='')
print(f'」の評価です。')7.7 AND条件
AND条件 は and
演算子を使って評価することができます。
%reset -f
x = 0 # 点AのX座標
y = 0 # 点AのY座標
if x==0 and y==0 : #「and演算子」を利用
print('点Aは原点上に存在します')
else :
print('点Aは原点以外に存在します')上記と同じ処理をするプログラムは、次のように条件分岐構文のネストでも構成できます。ただし、可読性・保守性に問題があることを実感してください。
and
演算子では、x==0 and y==0 and z==0 のように
3つ以上の条件 についての AND (論理積)
をとることもできます。
フォーム機能の活用
先に紹介したフォーム機能を利用することで、次のように操作性に優れたプログラムにすることができます。@title
に { run: "auto" }
を含めることで、スライダーを変更すると 自動実行 されるようになります。
# @title 座標の判定 { run: "auto" }
%reset -f
x = 0 #@param {type:"slider", min:-5, max:5, step:0.5}
y = 0 #@param {type:"slider", min:-5, max:5, step:0.5}
if x==0 and y==0 : #「and演算子」を利用
print('点Aは原点上に存在します')
else :
print('点Aは原点以外に存在します')自動実行が機能しない場合は、初回のみ Ctrl +
Enter
で手動実行してみてください。その後、スライダーを移動するとプログラムが自動実行されます。
7.8 OR条件
OR条件は or
演算子を使って評価することができます。
%reset -f
x = 1
y = 1
if x==0 or y==0 : #「or演算子」を利用
print('点AはX軸上もしくはY軸上に存在します')
else :
print('点AはX軸上にもY軸上にも存在しません')なお、文字列の等価性の比較は、card
を変数とすれば card == 'UR' のようにします。
card == URとすると、cardという変数と、URという変数の比較になってしまうので注意してください。card == 'UR'とすると、cardという変数と、'UR'という文字列との比較ができます。シングルクォーテーションで囲むか、囲まないかの使い分けができるようになってください。
以下に、文字列の比較と、ここまでに学習した内容の応用 (単なる組み合わせ) を示します。
%reset -f
import random
import time
from IPython.display import clear_output
cards = ['UR','SSR','SR','S'] # 排出リスト
card = random.choice(cards) # リストからランダムに1枚を取得
# 演出
for i in range(5):
print('.', end='')
time.sleep(0.5) # 0.5秒
clear_output() # 出力をクリア
# 指定のカードを得たときに追加メッセージ
if card == 'UR' or card == 'SSR' :
print(f'🎉おめでとうございます!', end='')
# 共通メッセージ
print(f'「{card}」をゲット!')第04行目 と 第13行目 の
clear_output
のみ新規の要素です。random.choice は 第02回講義、time.sleep
は 第01回講義
で学習済みです。
7.9 数値範囲条件
Pythonでは、次のように 数値範囲の条件 を与えることができます。
%reset -f
temp = 20 # 温度 (Temperature)
if 15 <= temp <= 25 : # tempが15以上25以下のとき「真」となる
print('正常です')
else :
print('正常範囲外です')他のプログラミング言語では、通常、次のようにAND条件を使って上記のような条件の評価をします。
7.9.1 演習4 ( 7分)
数値範囲条件の与え方1.py
について、フォーム機能を利用して「温度temp」がスライダーで与えられるようにしてください。また、スライダーが変更されると自動実行されるようにしてください。
7.9.2 演習5 ( 10分)
XY平面上に存在する点Aの座標を与えたとき、その値に応じて次の「いずれかの文章」を出力するプログラムを作成してください。可読性と保守性を意識しながら作成してください。
- 点Aは、第1象限のなかに存在します。
- 点Aは、第2象限のなかに存在します。
- 点Aは、第3象限のなかに存在します。
- 点Aは、第4象限のなかに存在します。
- 点Aは、原点上に存在します。
- 点Aは、X軸上に存在します。
- 点Aは、Y軸上に存在します。
%reset -f
import random as r
for i in range(5):
x = r.choice([-1,0,1])
y = r.choice([-1,0,1])
print(f'点A ({x},{y})は、')7.10 条件式の正体
x > 5 や
x==0、0<=x<=10
のような条件式は、次のように if文以外の場所 でも使うことができます。
%reset -f
x = 10
# x > 5 の評価結果を 変数var1 に格納
var1 = x > 5
# x == 0 の評価結果を 変数var2 に格納
var2 = x == 0
# 変数に格納された値を出力
print(f'var1={var1}, var2={var2}')上記の実行結果から分かるように、比較演算子を使った条件式は、True または False という
bool型 の値になります。
bool型 は、True または
False の2値から構成される値です。int型 (整数型) や
float型 (浮動小数点数型) と同様に変数に格納 (バインド)
することができます。
そのため、次のように利用することもできます。
%reset -f
x = -5
y = 12
z = 80
c1 = -10 <= x <= 10 # 条件式の評価結果をc1に格納
c2 = -15 <= y <= 15 # 〃 をc2に格納
c3 = -20 <= z <= 20 # 〃 をc3に格納
print('点Aは指定の空間内に',end='')
if c1 and c2 and c3 :
print('存在します。')
else :
print('存在しません。')変数に格納せずに、if
に直接的に条件を与えると次のようになります。
%reset -f
x = -5
y = 12
z = 80
print('点Aは指定の空間内に',end='')
if -10 <= x <= 10 and -15 <= y <= 15 and -20 <= z <= 20 :
print('存在します。')
else :
print('存在しません。')8 宿題
次回講義、6月4日(火) に「小テスト」を実施します。今回の授業で扱った「条件分岐構文」に関する Pythonプログラム を正しく記述できるようになっておいてください。
- elif、ネスト、AND条件、OR条件、数値範囲条件も含みます。
- 基本的な f文字列 を使った標準出力も含みます (書式指定子は含みません)。
- フォーム機能、繰り返し構文は含みません。