1 準備
- GoogleにログインしてGoogleColab.にアクセスしておいてください。
- GitHub にログインしておいてください。
2 前回の復習
前回講義で学んだことの要点をおさらいしておきます(少しだけ新規の内容が含まれています)。
ジュニアレベルのプログラマ(=ソフトウェアエンジニアのタマゴとして新卒就職しても困らないレベル)に到達するために必要な学習時間は 1,000~2,000 時間 。
プログラミング「超初心者( 未学習者 )」が「初心者」になるために必要な学習時間は 約250 時間。
授業は (復習に20分程度を要するので) 実質的には70分。それを1週間の間隔をあけて実施。
通年30回の授業は、累積で 70分×30回=2,100分= 35 時間。もしも、授業という枠内の「最低限の取組み」しかやらないなら、2024年3月になっても 初心者にすら到達できない。
あくまで学校の授業や実験実習は プログラミング学習の「チュートリアル」 という位置づけであり、プログラミングの「学び方」を学ぶ ためのものと考える。
授業を「きっかけ」として、自学することではじめてプログラミングの知識やスキルが養われていく。
- もし、第01回講義から今日までの2週間(14日間)。平日に「1日2時間」、土日に「1日5時間」のプログラミングに取り組んでいれば累積で「40時間」。既に授業を通年で受ける以上の勉強ができていることに。
- ゲームや部活動を「1日2時間、楽しむこと」は決して難しくない。事実、プログラミングを楽しんでいる「ガチ勢」は、1日2時間以上のプログラミングを楽しんでいる。将来、そういった人達が、就職活動のライバルとなり、仕事における同僚となります。
楽しく意欲的にプログラミングを学ぶ(自学する)ためには、自分が夢中になれる/没頭できるプロジェクトに (恐れずに) 飛び込んでみること、自然に学習せざるを得ない環境・枠組み・仕掛けのなかに身を置くこと ( 仲間や師匠をつくること) が大事。
- そのための環境は既に十分に整っている。少なくとも高専環境には「総合課題実習1」「プログラミング研究会」「高専祭展示」「サークル・同好会・勉強会 (クラスメイトと勝手に自由に結成) 」など。外部 (SNSや地域など) も環境はある。
- あとは「やるか」「やらなか」だけ (もはや「できない」という選択肢はすでに除外されている)。自分の人生をどのような方向にもっていくかは、自分が決定して、自分で責任を負うしかない。
- 馬を水辺に連れて行くことはできても、水を飲ませることはできない
オフラインの1人用ゲームが楽しめるのは、せいぜい100時間程度 (それ以上はプレイするモチベーションがつづかない) 。一方で、MMORPGなどのオンラインの協力プレイ型・対戦プレイ型のゲームは1000時間を超えても十分に楽しめる。この「違い」は何か? これをプログラミング学習にも上手に適用する (ゲームフィケーション)。
- If you want to go fast, go alone. If you want
to go far, go together.
【訳】早く行きたければ一人で行きなさい、遠くへ行きたければみんなで行きなさい - 自分にとって最適な環境とは「先生や親から与えられるのを待つもの」のではなく「自分自身で工夫して築き整えるもの」であるというが重要。自分という人間の性格を熟知し、それに適した環境を選択・構築することも能力であり才能である
- If you want to go fast, go alone. If you want
to go far, go together.
2.1 演習① ~前回の復習~
前回の学習内容です。どれだけ身についているでしょうか?
2.1.1 演習①-1
- GoogleColab.
にアクセスして
0427_数値を扱う変数とprint関数.ipynbという名前でノートブックを新規作成せよ。 - ノートブックの共有を有効化して「大阪府立大学工業高等専門学校」を「閲覧者」に設定せよ。今回もノートブックを提出してもらいます。
- ノートブックに「テキストセル」を追加し、次のように装飾された文字列が表示されるようにせよ
(マークダウン形式で記述する)。
- 下記の
end=''のような「等幅文字でプログラムコード等を示す文字装飾」を「コードスパン」と呼ぶ。
- 下記の
時間短縮のため、次のテキストをコピペして使用すること。
演習①-1
変数を埋め込んだ文字列の出力
文字列に変数を埋め込んで出力するためには「f文字列」を使用する。
改行をつけずにprint関数で文字列を出力するには、引数にend=’’を追加する。
2.1.2 演習①-2
- 実行結果として
"An eye for an eye, a tooth for a tooth" - Hammurabi's Codeという文字列を出力するように、04行目のprint関数の引数 (括弧の内部) を適切に設定し、実行し、結果を確認せよ。- 出力文字列に ダブルクォーテーション と アポストロフィ (シングルクォーテーション) の両方が含まれることに注意せよ。
- 変数
word1とword2を利用すること。
- コードセルの実行にはショートカットキー
(
Ctrl+Enter) を利用すること。
2.1.3 演習①-3
- 実行結果として
ディオ「無駄!無駄!無駄!無駄!無駄!無駄!無駄!無駄!無駄!無駄!無駄!無駄!無駄!無駄!無駄!ァーーーッ」という文字列(「無駄!」は15回)を出力するように、03行目のprint関数の引数を適切に設定して、実行し、結果を確認せよ。- 変数
wordを利用すること。 - for文を使わなくても可能であることは前回の講義のなかで示している (この講義資料のなかにもヒントはある)。
- このセリフの元ネタは ジョジョの奇妙な冒険。
- 変数
3 変数のクリア
Google Colab. において、あるコードセル内で作成(設定)した変数は 他のコードセルにも引き継がれます。実際に確認してみましょう (試してみましょう)。
コードセルを新規作成して次のプログラムをコピペして実行します
(コードセルを実行する場合は、積極的にショートカットキー
Ctrl+Enter を使用してください)。
次に、別のコードセルを新規作成して、次のプログラム「pg2.py」の内容をコピペして実行することを考えます。pg2.py
の01行目では、あえて変数名の タイポ
をしています。
上記プログラムを実行すると、01行目で文字列をセットしている変数名
wrod と、02行目で参照している変数名 word
が違うので NameError: name 'wrod' is not defined
というエラーがでるだろうと期待しますが、実際の結果はそうはなりません。
先に実行したセルで作成された変数 word
が内部に残っているのでエラーは発生しないものの、意図した結果が得られない
という状況になります。
今回は、変数名に間違いがあることに気づいているために問題ありません。しかし、間違いに気づいていないときに「エラーは発生しないものの、意図した結果が得られない」というのは非常に厄介な状況 (バグ) になります。実際、これが原因で何時間も悩んだり、学習を挫折したりする初心者も珍しくありません。
コードセルを抜けても変数が生き残っていることは非常に便利な機能なのですが、状況によっては望ましくありません。そのような状況で役立つのが、変数をオールクリアするための
%reset -f
になります。既に第01回の講義資料から登場しています (きょうまでに解説されるのを待つことなく、自分で検索等して解決した人は大変に素晴らしいです
)。
実際に、確認してみましょう。上記の2個目のプログラムを次のように書き換え
(%reset -fを追記し) 、実行してみてください。
今度はエラーが発生するようになりました (エラーが発生することで「不具合の原因がどこにあるか」のヒントが得られるようになりました)。
3.1 演習
%reset -f を%reset に書き換えて実行し
(-fオプションを抜いて実行し)、どのように動作が変わるかを確認せよ。
コマンドのオプション
一般にコマンドの「オプション」の
-f は「force
(強制する)」を意味します。例えば、Linuxにおけるファイル削除のコマンド
rm
は、通常「本当に削除してよいか」の旨の確認がされますが
rm -f
のようにオプションをつけると「確認なし」で削除が実行されます。
よって、次のような -f
オプションをつけたコマンドを安易に実行しないように十分に注意してください。
sudo rm -rf / --no-preserve-root
OS (Linux) が吹っ飛びます。
3.2 補足: マジックコマンド
GoogleColab. のコードセルのなかで %
から開始する文をマジックコマンドといいます。マジックコマンドは、Python
の文・機能ではなく、GoogleColab.(Jupyter) の文・機能であり、(Colab.以外の)ローカルのPython開発環境では使用できません。
一度は「Google Colab マジックコマンド」で検索してみてください。開発を効率的に進めることができる様々なマジックコマンドが存在しています。
4 変数の確認
GoogleColab. では、参照可能な変数
(定義されている変数) を %who
というマジックコマンドで確認することができます。
実際に確認してみましょう。コードセルを新規作成して、次のプログラムを実行してください。
次に、別のコードセルを新規作成して、次のマジックコマンドを実行してください。
現時点で定義済みの変数が表示されます。また、%whos、%who_ls
のマジックコマンドについても動作を確認してみてください。
その後、%reset -f
を実行後、再度、各マジックコマンド
(%whoや%whos)
を実行して結果を確認してみてください。
5 変数に「数値」を代入して取り扱う
5.1 導入
ここまでは「変数」に文字列 (文字列リテラル) を代入するプログラムを扱ってきました (リテラルとは?)。その際、注意すべきことは、次のように 文字列をダブルクォーテーション、または、シングルクォーテーションで囲んで扱う (表現する) ということでした。
%reset -f
apple = 'りんご'
banana = "バナナ"
toeic_score = '350' # 文字列としての350
print( "apple = " + apple )
print( f'3-banana => {banana * 3}' )
print( f'TOEICスコア倍増! 目指せ{toeic_score * 2}')特に、上記を実行した際、07行目の文によって出力される文字列に注意してください
(どのような結果になるか、予想の上、実行してみてください)。ここで変数
toeic_score
に格納されている「350」は「数値」ではなく「文字列」であるため、期待するような振る舞いはしません。
これは、f文字列の内部の特有の振る舞いではなく、次のようにプログラムを書いた場合でも同じです (期待するような文字列出力を得ることはできません)。
%reset -f
toeic_score = '350' # 文字列としての350
toeic_double_score = toeic_score * 2
print( '目指せ' + toeic_double_score )5.2 変数に数値を代入
ここからは、変数に数値 (\(\neq\)文字列) を代入することを考えていきます。
中級者向け: 厳密には代入ではなくバインド(束縛)
前回も解説したように「整数値を変数に代入する」という表現は厳密には正しくありません (束縛する(バインドする)という表現が正しいです)。ただし、ここでは初心者向けに厳密さをある程度犠牲にして分かりやすさを重視して表現していることをご理解ください。
詳しくは 小山高専・技術支援室 を参照してください。
変数に数値 (\(\neq\)文字列) を代入するときは、次のようにシングル/ダブルクォーテーションで囲まずにイコールの右辺に数値を与えます。
また、pi=3.14 のように
小数部を含む実数
を変数に代入することもできます。
なお、次のように f文字列 に埋め込まず、print関数の引数に直接変数を与えて、その内容を出力すること (表示すること) もできます。
%reset -f
toeic_score = 350
toeic_double_score = toeic_score * 2
print( toeic_score )
print( toeic_score, toeic_double_score )また、次のように、直接、計算式を与えることもできます。
5.3 Pythonで利用できる数値リテラル
Pythonでは、toeic_score = 350 や
pi=3.14 以外にも、次のような数値リテラル
(数値の表記)
を使って変数に値を代入することができます。
桁数の大きな値 (例えば、300,000,000 = 30億) は、次のように与えることができます。
%reset -f
x1 = 300000000 # ノーマルな方法(ミスしやすい)
print(f'x1 = {x1}')
x2 = 300_000_000 # アンダーバーを数値区切りに利用
print(f'x2 = {x2}')
x3 = 3e+8 # e 3x10^8
print(f'x3 = {x3}')2進数( Binary:
バイナリ ) は、次のように先頭に 0b
を付けて与えることができます (先頭に付ける文字を「prefix
(プレフィックス)」、「接頭辞/接頭辞」とも表現します)
。また、10進数の場合と同様に、任意の位置 (好きな位置) に
_ を入れることができます。
%reset -f
x1 = 0b1010 # 1010 => 8 + 2 = 10
print(f'x1 = {x1}')
x2 = 0b_1010 # 1010 => 8 + 2 = 10
print(f'x2 = {x2}')
x3 = 0b_0011_1010 # 0011 1010 => 32+16+8+2=58
print(f'x3 = {x3}')注意
第01講義、第02回講義でも注意しましたが、解説を受ける / 解説を読む だけではなく、必ず手を動かして自分自身で「試してみること」「検証してみること」、また「例外はないのか?などについて考えてみること」を忘れないでください。
例えば、プレフィックスであれば「0B
のような大文字でもよいのか」「00Bのようなゼロ2連続でもよいのか」、
数値区切りのアンダーバーであれば「2個連続で使えるのか」「数値リテラルの先頭や末尾でも使えるのか」「プレフィックスの途中で
0_b_1100
のように使えるのか」のようなことが発想ができ、結果を予想し、それを試して、規則性などを見いだせるようになってください
(このようなことができる人が最終的に高いスキルを習得できます)。
また、同時に、いま学んでいることが「日常の生活や教科学習では、どのように利用できそうか」「自分がつくりたいモノ (例えばゲーム) にどのように利用できそうか」という視点も常に持つようにしてください。
16進数( Hexadecimal: ヘクサデシマル ) は、次のように与えることができます。16進数の「A」から「F」は大文字でも、小文字でも、どちらでも表記できます。
%reset -f
x1 = 0xFF
print(f'x1 = {x1}')
x2 = 0xff
print(f'x2 = {x2}')
x3 = 0x_ffEE6a # 大文字と小文字の混合
print(f'x3 = {x3}')5.4 四則演算
「整数」または「小数を含む実数」が数値が格納された変数に対しては、次のように四則演算をすることができる。
%reset -f
a, b = 7, 2 # a=2 と b=6 を1行で記述
x = a + b #「x1=a+b」のようにスペースを含めず記述も可
print(f'(1) {a}+{b}={x}')
x = a - b
print(f'(2) {a}-{b}={x}')
x = a * b # 乗算(掛け算)。「*」はアスタリスクと読む。
print(f'(3) {a}*{b}={x}')
x = a / b # 除算(割り算)
print(f'(4) {a}/{b}={x}')
x = a % b # 何を計算しているか検証せよ。
print(f'(5) {a}%{b}={x}')
x = a // b # 何を計算しているか検証せよ。
print(f'(6) {a}//{b}={x}')上記の (5) と (6) については、変数の値を変更しながら「何を計算しているのか」を検証してください。特に、変数に格納される値が「小数」や「負数」となったとき、どのような挙動をするのかも、検証してください。
5.4.1 演習②
変数 a に10、変数 b に5、変数
c
に2を代入して次の値を計算せよ。さらに、正しく計算できているかどうかを、手計算やExcelを使用した計算、周囲の学生と突き合わせることで検証せよ。
\[ (1)\ \ \ 6ab^{2} \]
\[ (2)\ \ \ -3(a+b)\{(a+c)-(b+c^2)\} \]
\[ (3)\ \ \ -\frac{3b^2}{6a+2c} \]
注意
ChatGPT等の登場により「(正当性の保証はないものの) とりあえずの答えをだすこと」は、ほぼ誰でも「できてしまう時代」となりました。そのうえで、重要なことのひとつとして「解の検証」があります。
「情報1」や「情報2」の授業でも伝えているように「技術者には自分自身で解の妥当性を検証し、それに責任を負うことが求めれる」ということを意識して、そのための訓練や習慣づくりをするようにしてください。
5.5 出力の書式指定
変数に格納した数値を、文字列として出力する際、次のように
書式 (フォーマット)
を指定することができます。f文字列のなかで、:
に続けて書式指定子を記述します。
%reset -f
a = 45 # 整数値
print(f'a={a}') # 書式指定なし
print(f'a={a:.2f}') # 小数点以下桁数指定
print(f'a={a:b}') # 2進数 1+4+8+32
print(f'a={a:_b}') # 2進数 区切り文字あり
print(f'a={a:09_b}') # 2進数 ゼロ埋め・出力桁数指定
print(f'a={a:x}') # 16進数 13+32
print(f'a={a:X}') # 16進数 大文字
print(f'a={a:04X}') # 16進数 ゼロ埋め小数を含む場合の例を示します。特に桁数が指定されたとき、四捨五入されるのか、切り捨てられるのか、切り上げられるのか、それともそれ以外なのか、予想し、検証してください。
%reset -f
a = 0.62184 # 実数
print(f'a={a}') # 書式指定なし
print(f'a={a:.3f}') # 小数点以下の桁数指定
print(f'a={a:.4f}') # 小数点以下の桁数指定
print(f'a={a:e}') # 指数表示
print(f'a={a:.3e}') # 指数表示+桁数指定
print(f'a={a:.3E}') # 指数表示
print(f'a={a:%}') # パーセント
print(f'a={a:.1%}') # パーセント+桁数指定このほかにも多数の書式が存在します。必要に応じて「python f文字列 書式指定」などでウェブ検索して使えるようになっておいてください。
頻繁に使用する書式以外を暗記する必要はありませんが、その存在を意識して、必要に応じて利用できるようになっておいてください。
5.5.1 補足1
単位のSI接頭辞(SI接頭語)に関連した変換は、次のようにできます。
%reset -f
x = 42195 # 42195(m)
print(f'{x:,}(m)は、{x*1e-3}(km)です')
print(f'{x:,}(m)は、{x/1000}(km)です')5.5.2 補足2
f文字列は、print関数の引数として使用することが多いですが、独立して使用することもできます。
5.6 丸め誤差
第03回の情報の授業で学習したように、10進数表記では有限小数となる数値が、2進数表記では無限小数になることがあり、また、コンピュータのメモリ (記憶領域) が有限であることから、コンピュータで小数を扱う場合は 丸め誤差 が生じます。これは Python でも同様で、特に金融計算を扱う場合には、特に注意する必要があります。
中級者向け: decimalモジュール
decimalモジュール を使用することで、計算に「0.1」や「0.2」を含む場合でも誤差なく正確な計算ができるようになります。ただし、通常の計算にdecimalモジュールを使うことには相応のデメリットがあります (考え、調べて、検証してみましょう)。
5.7 べき乗の計算
べき乗の計算には、** 演算子を使用します
(Excelではべき乗の計算に ^ を使用します)。
上記では変数を経由していますが、次のように変数を使わずに同じ出力を得ることもできます。
また、**
演算子を使用することで平方根や、3乗根、4乗根を求めることもできます。
\[ \sqrt{256} = 256^{1/2} = 256^{0.5} = 16\]
6 宿題
ここまでの「演習①」「演習②」に加え、次の「演習③」を今回のノートブック上で取組め。どうしても意欲が湧かない場合は、2時間を費やしてできるところまでもOKです (もちろん、何時間かけてもOKです。将来への投資です)。
どうしても解決できないことがあれば、LINEでスクリーンショットと共に質問もOKです。
6.1 演習③
Pythonを利用して、次の各問いの答えを求めよ。また、求めた答えが正しいものであることを、何らかの方法(手計算、関数、電卓アプリ、Excel、別ロジックのPythonプログラム、別のプログラミング言語など)を使って検証せよ。
6.2 演習③-1
(「情報2」の講義ノート p.25 より)
CPUのクロック周波数が2.1GHzのとき、そのクロック周期が何秒になるかを計算せよ。なお、X.XXXe-XX
のような指数の形式による出力と、SI接頭語 ( μs or ns or ps )
を用いた XXXX(ps)
のような形式による出力を得ること。
6.3 演習③-2
(「情報2」の講義ノート p.30 の脚注より)
電気信号が伝わる速さは「光速」とほぼ同じで約 \(3\times 10^{8}\) (m/s)
である。CPUのクロック周波数が \(2.8\)(GHz)
のとき、そのクロック周期に相当する時間のなかで電気信号が進む距離を
XXX.X(cm)
の形式で出力せよ。小数点以下は1桁で答えること。
6.4 演習③-3
次の16進数を2進数と10進数に変換せよ。
\[(1)\ \ \ (\mathrm{FFFF}\ \mathrm{FC00})_{16}\] \[(2)\ \ \ (\mathrm{1000}\ \mathrm{0101})_{16}\]
6.5 演習③-4
次の2進数を16進数に変換せよ。
\[(1)\ \ \ (0011\ 0101\ 1010)_{2}\] \[(2)\ \ \ (1001\ 0110\ 0011)_{2}\]
6.6 演習③-5
現在までに学習した「物理」や「数学」、その他の「専門科目」に関する問題 (主に計算問題) をテキストセルに記述し、それを Python を使って解け。