スコープ
ローカル/グローバル/self
STUDY GUIDE · オブジェクト指向型言語
期末試験対策 · 第9–10・12–14回本線 · 案β(MD正本)
テキスト正本は runs/ool-final/content/。入門で用語を固めてから、演習と同型コードを手で書くドリルへ。中間(第2–7回)は別サイト。第11回は休講想定で欠番。
期末試験の正式な問題形式は資料に明記されていない。以下は宿題・演習の型から推定した想定であり、断定ではない。
| 本線 | 第9・10・12・13・14回+7/7追加(スコープ/ポリモーフィズム/標準・外部ライブラリ/tkinter/Canvas/継承復習) |
|---|---|
| 復習 | 第2–7回は中間サイトへ誘導: https://ool-midterm.pages.dev/ |
| 欠番 / OOS | 第1回(未入手)/第8回(中間試験日の可能性大)/第11回(休講想定・欠番) |
| 日程メモ | 第14回資料: 7/21 休講、7/28 期末試験 |
| 推定形式 | (1) クラス実装+継承+ポリモーフィズム呼び出し (2) import/標準・外部ライブラリ (3) tkinter 部品+Var (4) Canvas 画像・move |
| 狙い | 演習問題と同じ/ほぼ同じコードを白紙から書けること(用語暗記だけでは足りない) |
期末でよく出る骨格チート
詳細は各ドリルの答案型。試験開始直後にこの形を思い出す。
# 継承+ポリ
class Parent: ...
class Child(Parent):
def __init__(self, ...):
super().__init__(...)
def meth(self): ...
def call(obj): return obj.meth()
# import
import random / import math / from PIL import Image
import tkinter as tk
# GUI
base = tk.Tk()
# Widget + Var + pack + command
base.mainloop()
# Canvas 移動
canv.move(tag, dx, dy); canv.update()
# 絶対座標
canv.coords(tag, x, y)
初見の既定は「学ぶ」。ドリル強制はしない(expertise reversal)。
第2–7回(クラス・self・継承の土台)の厚い解説は中間専用サイトに分離した。URL を増やさないため、期末は後半本線に集中する。
正本は runs/ool-final/content/concepts/*.md(案β)。まずスコープ・変数・ポリモーフィズムを日常語で固め、長い実装はドリルへ。
入門を一通り読んでから本編・手書きドリルへ(入門完了前の本編 L3 飛ばし禁止)。
なぜ必要か: クラスや関数を書くと、見た目同じ `v` や `area` が何種類も出てくる。どれが生きているかを見誤ると、「さっき代入したのにエラー」「値が戻らない」が止まらない。スコープを先に押さえると、以降のクラス変数・ポリモーフィズムの説明がつながる。
変数が「どこまで使えるか」という**有効範囲**のこと。同じ名前でも、置いた場所が違えば別物として扱われる。
別名: 有効範囲。英語 scope。
関数の中で v=20 と書いた
その呼び出し中だけ 20 が見える
仕組み(言葉)
代入した場所のブロックが、その名前の寿命と見える範囲を決める。関数の中での代入は、その関数専用の枠を作ることが多い。ファイルの先頭(どの def/class にも入っていない場所)での代入は、ファイル全体から名前で参照できる枠になる。
教室の黒板(みんなから見える場所)と、自分のノート(自分の席だけで見える場所)がある、と考える。ノートに書いた答えは隣の席から見えない。プログラムでも「どの黒板/ノートに書いたか」がスコープ。
v = 10 # ファイル全体で見える側
def printer():
v = 20 # この関数の中だけの別枠
print(v) # → 20
printer()
print(v) # → 10(上の別枠は消えている)
前後比較(コード無し):
| 前 | 後 |
|---|---|
関数の中で v=20 と書いた | その呼び出し中だけ 20 が見える |
関数の外で print(v) | ファイル先頭の 10 のまま(中の枠は消えた) |
※「外」の基準点=その変数を定義した関数ブロックの外。
なぜ名前が同じ v なので、「1つの箱を上書きしている」と脳が読む。
NG「関数内で v=20 したから、外の print(v) も 20」と思う。
正し方関数内の代入で別枠のローカルが生まれる。外の枠は触っていない。
補足global 宣言で外を書き換える話は発展。講義の基本は「枠が分かれる」理解でよい。
試験での答え方
なぜ必要か: 面積などの一時計算は、メソッドを出たら捨ててよいことが多い。一方、設定値のようにファイル全体で共有したい値もある。寿命を分けないと、「メソッドを抜けたあと `print(area)` したらエラー」や「意図せず全体の値を書き換えた」が起きる。
**ローカル**は、ある関数(またはメソッド)のブロックの中だけで生きる変数。**グローバル**は、ファイルのトップレベル(どの `def`/`class` の外でもない場所)で定義された変数で、ファイル全体から名前で参照できる。
別名: local / global。
同じ名前/同じ見た目だと、全部ひとまとめに見えてしまう
会議中だけのメモ用紙(ローカル)と、共用ホワイトボード(グローバル)。会議が終わるとメモ用紙は捨てるが、ホワイトボードの字は残る。
仕組み(言葉)
Python は「どこで代入したか」を見て枠を決める。関数の中で代入すると、その関数用の名前表に載る。トップレベルで代入すると、ファイル用の名前表に載る。メソッド内で self. 無しの代入はローカルであり、オブジェクトの属性にはならない。
会議中だけのメモ用紙(ローカル)と、共用ホワイトボード(グローバル)。会議が終わるとメモ用紙は捨てるが、ホワイトボードの字は残る。
g = 1 # グローバル
def f():
area = 3.14 * 2 # ローカル(f の中だけ)
print(area)
f()
# print(area) # → エラー(定義した関数ブロックの外からは見えない)
print(g) # → 1
| 種類 | 定義場所 | 定義した関数の外から参照 | 寿命 |
|---|---|---|---|
| ローカル | 関数/メソッドの中 | 不可 | 呼び出しが終わるまで |
| グローバル | ファイル先頭(トップレベル) | 可 | ファイル実行中 |
※「外」の基準点=その変数を定義した関数ブロックの外。
なぜメソッド内で area = … と書くと、「円の面積をオブジェクトが覚えた」ように見える。
NGself. 無しの area を、あとから c.area で取り出そうとする。
正し方area は呼び出し中の一時メモ。オブジェクトに残すなら self.area = …。
補足クラス変数との違いは C03。
試験での答え方
なぜ必要か: 円ごとに違う半径はインスタンス変数。全円で共通の定数っぽい値やカウンタはクラス変数向き。混ぜると「1つの円を変えたら全部変わった」や「`self.` を付け忘れてローカルになった」が起きる。
**インスタンス変数**は、オブジェクト1つごとに持つデータ(`self.名前`)。**クラス変数**は、同じクラスのオブジェクトが**共有**するデータ(クラス本体に直接書いた変数)。
別名: インスタンス属性 / クラス属性。
同じ名前/同じ見た目だと、全部ひとまとめに見えてしまう
学籍番号は学生一人ひとり違う(インスタンス)。学校名は同じクラス(同じ学校)の全員で同じ札を見るイメージ(クラス変数)。
仕組み(言葉)
self.r = … は「今のこのオブジェクト専用の引き出し」にしまう。クラス本体の kind = … は「クラスの共用引き出し」。メソッド内で r = … のように self. 無しだと、それはローカル変数であり、どちらにも残らない。
学籍番号は学生一人ひとり違う(インスタンス)。学校名は同じクラス(同じ学校)の全員で同じ札を見るイメージ(クラス変数)。
※「共有」の基準点=同じクラスから作られた各インスタンスのあいだで、クラスに置いた1つの枠を見ている、という意味。
class Circle:
kind = "円" # クラス変数(共有)
def __init__(self, r):
self.r = r # インスタンス変数(個体ごと)
a = Circle(2)
b = Circle(5)
print(a.r, b.r) # → 2 5(別々)
print(a.kind, b.kind) # → 円 円(同じ枠を見ている)
| 種類 | クラス外からの読み方 | クラス内での典型 |
|---|---|---|
| インスタンス変数 | インスタンス.名前 | self.名前 |
| クラス変数 | クラス.名前 または インスタンス.名前(読み出し) | クラス本体に直接定義 |
なぜself. を付け忘れると「変数を書いたつもり」になりやすい。
NGメソッド内 area = 3.14 * self.r ** 2 のあと print(obj.area) で取り出す。
正し方残したいなら self.area = …。付けない area はメソッド終了で消える。
補足クラス変数を インスタンス.名前 = で代入すると個体側に影ができることがある(発展)。
試験での答え方
self./クラス.)と「誰のものか」を書く。self/共有(基準点付き)。なぜ必要か: 円も正方形も「面積を求める」なら、使う側は毎回クラス名で分岐したくない。同じ `area()` というボタンを押せば、中身は相手が勝手にやる——そう書けると、あとから新しい図形を足しても呼び出し側が壊れにくい。
**同じ呼び方(同じメソッド名)で、相手の種類ごとに違う処理をさせる**考え方。使う側は「相手が誰か」を細かく分けず、同じ窓口から呼べる。
別名: 多態性。本稿ではポリモーフィズム。
相手ごとに別関数を呼び分ける
同じ関数/同じメソッド名に渡す
仕組み(言葉)
異なるクラスに同じ名前のメソッドを用意する。呼び出し側は「そのオブジェクトのそのメソッド」を実行するだけなので、渡した相手のクラスに応じて中身が切り替わる。継承+オーバーライドでも同じ形になる(親の型として扱い、子の実装が動く)。
車種が違っても、発進は同じ「Aボタン」。押す動作は同じで、中のエンジンのかかり方は車ごとに違う。使う人は車の内部を知らなくてよい。
前後比較(コード無し):
| 前 | 後 |
|---|---|
| 相手ごとに別関数を呼び分ける | 同じ関数/同じメソッド名に渡す |
| 「円用・正方形用」と分岐だらけ | 窓口は1つ、中身だけ違う |
class Dog:
def speak(self):
return "わん"
class Cat:
def speak(self):
return "にゃ"
def intro(obj):
return obj.speak() # 同じ窓口
print(intro(Dog())) # → わん
print(intro(Cat())) # → にゃなぜ「同じメソッド名」と「同じ処理」が頭の中でくっつく。
NGポリモーフィズム=中身も必ず同じ、と思い込む。
正し方名前(呼び方)は揃える。処理の中身はクラスごとに違ってよい(それが本丸)。
補足講義の車のたとえ=操作は統一、発進の仕方は違う。
試験での答え方
なぜ必要か: 「動物は鳴く」は親で共通に置きたいが、犬は「わんわん」、蛇は「シャー」と変えたい。共通部分は親、違う部分だけ子で上書きすると、重複を減らしつつポリモーフィズムが使える。
親クラスで定義したメソッドを、子クラスが**同じ名前で書き直して上書き**すること。
別名: 上書き。英語 override。
同じ名前/同じ見た目だと、全部ひとまとめに見えてしまう
会社の「挨拶マニュアル(親)」がある。部署ごとに一言だけ差し替えるのがオーバーライド。マニュアル全体をゼロから別冊にするのではない。
仕組み(言葉)
子クラスに親と同じメソッド名があると、そのインスタンスでは子の定義が優先される。呼び出し側は obj.cry() のままでよい(ポリモーフィズムとセットで使う)。
会社の「挨拶マニュアル(親)」がある。部署ごとに一言だけ差し替えるのがオーバーライド。マニュアル全体をゼロから別冊にするのではない。
class Animal:
def cry(self):
return "鳴く"
class Dog(Animal):
def cry(self): # 同名で上書き
return "わんわん"
print(Dog().cry()) # → わんわん(親の「鳴く」ではない)
| 用語 | 役割 |
|---|---|
親の cry | 共通の型・デフォルト動作 |
子の cry | 同じ入り口で中身だけ差し替え |
なぜ継承とセットで出るので、「継承すれば自動で鳴き方が変わる」と思いがち。
NG子クラスを作っただけで、親と同じ "鳴く" のままなのに「オーバーライドした」と言う。
正し方同名メソッドを子側に書いて初めて上書き。書かなければ親のまま。
補足親の処理も使いたいときは super()(C13/ドリル D10)。
試験での答え方
なぜ必要か: 毎回ゼロから乱数や日付を書くのは無駄で、ミスも増える。用意された道具を `import` して使うと、試験の実装も短く正確になる。階層の名前を取り違えると「何を import すればいいか」が曖昧になる。
プログラミングの**道具セット**の階層。ライブラリが大きな道具箱、その中の一つ一つの道具(`.py`)がモジュール、モジュールをフォルダにまとめたものがパッケージ。
別名: 本稿ではこの呼び方のみ(道具箱たとえ)。
同じ名前/同じ見た目だと、全部ひとまとめに見えてしまう
工具箱一式=**ライブラリ**。中のプラスドライバ一本=**モジュール**。ドライバセットの引き出し(複数モジュール入り)=**パッケージ**。ねじを締める動作が、モジュール内の関数やクラスのメソッド。
仕組み(言葉)
使いたい道具を名前で読み込むと、その中の関数・クラス・定数が使える。標準で付いてくるものと、後から入れるものがある(C08)。
工具箱一式=ライブラリ。中のプラスドライバ一本=モジュール。ドライバセットの引き出し(複数モジュール入り)=パッケージ。ねじを締める動作が、モジュール内の関数やクラスのメソッド。
import math
print(math.pi) # モジュール math の定数
from math import sqrt
print(sqrt(9)) # → 3.0
| 用語 | 役割(関係) |
|---|---|
| ライブラリ | モジュール/パッケージの集まり(道具箱全体) |
| モジュール | 1つの .py(1つの道具) |
| パッケージ | 複数モジュールをまとめたディレクトリ |
部品の列挙だけで終わらず、「箱→中の道具→使い方(関数/クラス)」の関係で覚える。
なぜ「ライブラリ」「モジュール」が日常語でも似た感じで使われる。
NG「ライブラリを import した」とだけ言い、実際に読んだ .py(モジュール)名を言えない。
正し方コード上で読む単位はだいたいモジュール名(例: math)。ライブラリは「その仲間全体」の呼び名。
補足講義スライドのドライバたとえと対応づける。
試験での答え方
なぜ必要か: 標準ライブラリでも外部でも、読み込まないと使えないものが多い(組み込み関数は例外)。書き方を間違えると `NameError` や長い名前の打ち間違いが続く。
他のファイル(モジュール)の道具を、今のプログラムに**読み込んで名前を付ける**書き方。`import` 全体、`from` 一部、`as` は短い別名。
別名: 読み込み文。from / as を含む。
同じ名前/同じ見た目だと、全部ひとまとめに見えてしまう
本棚から本を借りる。 - `import calendar`=本を一冊まるごと借り、読むとき「calendar の ○○」と言う。 - `from calendar import month`=必要な章だけコピーして、`month` と短く
仕組み(言葉)
import はモジュールの名前空間を今のファイルに結びつける。from はそこから特定の名前だけを今の名前表に取り込む。as は結びつけた名前のラベルを短くするだけ。
本棚から本を借りる。
import calendar=本を一冊まるごと借り、読むとき「calendar の ○○」と言う。from calendar import month=必要な章だけコピーして、month と短く呼ぶ。as cal=借りた本に「cal」という付箋名を付ける。import calendar
calendar.month(2026, 7)
import calendar as cal
cal.month(2026, 7)
from calendar import month, isleap
month(2026, 7)
isleap(2024) # → True
| 書き方 | 効果 |
|---|---|
import 名 | 名.関数 で使う |
import 名 as 別名 | 別名.関数 |
from 名 import 部品 | 部品 を直接呼ぶ |
組み込み(例: print)は import 不要。標準モジュールは import が必要——この差が試験のひっかけになりやすい。
なぜfrom math import sqrt のあと、つい math.sqrt と書いてしまう(またはその逆)。
NGfrom math import sqrt なのに math.sqrt(9) で呼ぶ。
正し方取り込んだ書き方に合わせて呼ぶ。from なら sqrt(9)、import math なら math.sqrt(9)。
補足abs は組み込み、math.fabs はモジュール側(第10回の対比)。
試験での答え方
なぜ必要か: 乱数や数学は標準で足りることが多い。画像処理(Pillow)のように、標準に無い道具は `pip install` してから使う。区別できないと「なぜエラー?」の切り分けができない。
**標準**は Python を入れたときに最初から付いてくる道具(ただしモジュールは `import` が必要)。**外部**は別途インストールするもの(例: Pillow)。どちらも使い始めは `import`。
別名: 標準ライブラリ / 外部ライブラリ。
同じ名前/同じ見た目だと、全部ひとまとめに見えてしまう
スマホの初期アプリ=標準。アプリストアから追加したアプリ=外部。どちらも「開いて使う」必要があるが、後者は先にダウンロード(インストール)がいる。
仕組み(言葉)
標準モジュールは環境にあらかじめある。外部は PyPI などから入れ、そのあと標準と同じく import して関数/クラスを使う。画像なら open でオブジェクトを得て、show や属性(height 等)で操作する。
スマホの初期アプリ=標準。アプリストアから追加したアプリ=外部。どちらも「開いて使う」必要があるが、後者は先にダウンロード(インストール)がいる。
標準(import のみ):
import random
print(random.randint(1, 6))
外部(インストール後):
from PIL import Image
img = Image.open("hana.jpg")
img.show()
| 標準ライブラリ | 外部ライブラリ | |
|---|---|---|
| 入手 | Python 同梱 | pip install など |
| 使用 | import | インストール後に import |
| 例 | random, math, tkinter | Pillow(PIL) |
※ Pillow はパッケージ名と import 名(PIL)が違う点に注意。
なぜ「標準=import 不要」と思い込む(組み込み関数と混同)。
NGrandom.randint を import なしで使う。
正し方組み込み関数(print, abs 等)だけが import 不要。標準モジュールは import 必要。
補足長い画像加工チェーンはドリル/宿題側。概念では open→show まで。
試験での答え方
なぜ必要か: 期末本線ではチェック/ラジオ/キャンバスなど「画面を作って動かす」問題が出る想定。コンソールの `print` だけでは足りない。窓の作り方と部品の置き方の型を持っておく必要がある。
Python 標準の **GUI(画面付きアプリ)用ツールキット**。窓(ウィンドウ)の上にボタンやラベルなどの部品(ウィジェット)を置いて、クリックなどの操作に処理をつなぐ。
別名: Tkinter / GUI ツールキット。
部品を作っただけ
まだ画面に並ばない
仕組み(言葉)
Tk で土台の窓を作る。Button や Label など部品クラスでウィジェットを作る(親は土台)。pack 等で並べる。command で関数を結びつける。mainloop で表示を維持する。長い画面(飲料UI・攻撃ボタン一式)はドリル側。
紙の工作キット。土台の厚紙がメインウィンドウ、シールがボタンやラベル。シールを貼る=pack などで配置。押したら動く仕組みを紐づける=command。
import tkinter as tk
base = tk.Tk()
btn = tk.Button(base, text="PUSH!!")
btn.pack()
base.mainloop() # 画面を出し続ける
前後比較(コード無し):
| 前 | 後 |
|---|---|
| 部品を作っただけ | まだ画面に並ばない |
pack(など)で配置 | 見える位置に並ぶ |
mainloop | 窓が開いたまま操作を待ち続ける |
なぜ部品を生成した瞬間に画面に出ると思いがち。
NGButton(...) だけで pack も mainloop も書かない。
正し方作る・置く・回すの3段。置かないと見えない。回さないと一瞬で終わる/固まる。
補足side / anchor は配置の微調整(第12回)。
試験での答え方
なぜ必要か: 普通の Python 変数だけだと、チェックのオンオフや入力文字を部品から取り出しにくい。ウィジェット変数をはさむと、「今チェックされているか」「今選ばれている value」を試験で聞かれても答えられる。
画面の部品(入力欄・チェック・ラジオ)と**連動する専用の変数オブジェクト**。部品の状態が変わると値が変わり、`get` / `set` で読み書きする。
別名: コントロール変数。StringVar 等。
同じ名前/同じ見た目だと、全部ひとまとめに見えてしまう
スイッチとランプをつなぐ電線。スイッチ(チェックボタン)を倒すと、電線の先の状態表示(変数)が True/False に変わる。ランプを直接いじるのではなく、電線(変数)を見る。
仕組み(言葉)
部品に variable= や textvariable= でウィジェット変数を渡す。ユーザー操作で部品が変わると変数側も更新される。プログラムから set すれば初期表示も変えられる。状態の取得は get。
スイッチとランプをつなぐ電線。スイッチ(チェックボタン)を倒すと、電線の先の状態表示(変数)が True/False に変わる。ランプを直接いじるのではなく、電線(変数)を見る。
※「連動/見える」の基準点=そのウィジェット変数を variable / textvariable で結びつけた部品から見た状態。
import tkinter as tk
base = tk.Tk()
bln = tk.BooleanVar()
bln.set(True) # 初期オン
cb = tk.Checkbutton(base, text="ON", variable=bln)
cb.pack()
# あとで: bln.get() → True/False
| クラス | 向き |
|---|---|
StringVar | 文字列(Entry / Label の textvariable) |
BooleanVar | True/False(Checkbutton) |
IntVar | 整数(Radiobutton の value と一致させる) |
なぜ普通の x = True とウィジェット変数を同一視する。
NGCheckbutton に普通の bool を渡して状態を取ろうとする。
正し方BooleanVar 等のインスタンスを渡し、get/set で扱う。
補足ラジオは IntVar の値と各ボタンの value が一致したとき選ばれる。
試験での答え方
なぜ必要か: 飲料を複数注文したいならチェック、ランチセットを1つだけ選ぶならラジオ、と用途が違う。変数の型も違う(BooleanVar の並び vs IntVar+value)。取り違えると UI 仕様が宿題と食い違う。
どちらも「選ぶ」ための GUI 部品。**チェック**はグループ内で**複数オン**にできる。**ラジオ**はグループ内で**どれか1つだけ**選ぶ。
別名: Checkbutton / Radiobutton。
同じ名前/同じ見た目だと、全部ひとまとめに見えてしまう
学食の伝票。トッピングをいくつでも付ける=チェック。日替わりA/B/Cはどれか一つ=ラジオ(昔のラジオの押しボタンは1つ押すと他が戻る)。
仕組み(言葉)
チェックは部品ごとにオンオフの枠を持つ。ラジオはグループで1つの IntVar を共有し、各ボタンに違う value を付ける。ユーザーが押すと変数がその value に変わり、一致するボタンだけが選択表示になる。
学食の伝票。トッピングをいくつでも付ける=チェック。日替わりA/B/Cはどれか一つ=ラジオ(昔のラジオの押しボタンは1つ押すと他が戻る)。
チェック(複数可):
# bln1, bln2 はそれぞれ BooleanVar
# Checkbutton(..., variable=bln1)
# Checkbutton(..., variable=bln2)
# 両方 True になり得る
ラジオ(1つだけ):
# v = IntVar(); v.set(1)
# Radiobutton(..., variable=v, value=1)
# Radiobutton(..., variable=v, value=2)
# 選ばれているのは v.get() と一致する value の1つ
| チェックボタン | ラジオボタン | |
|---|---|---|
| 同時選択 | 複数可 | グループ内1つ |
| 典型変数 | BooleanVar(部品ごと) | IntVar(グループで共有) |
| 状態の見方 | 各 get() が True/False | 共有変数の get() が value |
なぜ「選ぶ部品」として同じ棚に並んで見える。
NGランチ3択に Checkbutton を3つ付けて「1つだけ選ばせる」つもりになる。
正し方1つだけならラジオ+共有 IntVar。複数可ならチェック+BooleanVar 複数。
補足for+辞書で部品生成を短くするのはドリル(D06/D07)。
試験での答え方
なぜ必要か: キャラ画像を出したり、攻撃ボタンで相手方向へ動かしたりする宿題の土台。相対移動と絶対移動を混同すると「一回動いたら変な場所に飛ぶ」になる。
Canvas は、線・円・画像・文字を載せる**絵を描く台**。`move` は今の位置から相対的にずらす。`coords` は中心座標を絶対指定で置き直す。
別名: キャンバス。move / coords。
同じ名前/同じ見た目だと、全部ひとまとめに見えてしまう
黒板にマグネットを貼る台=Canvas。 - `move`: 「今の場所から右へ10、下へ50」と**ずらす**(相対)。 - `coords`: 「中心を (200, 300) に**置き直す**」(絶対)。
仕組み(言葉)
create_image などで図形にタグを付ける。あとからタグを指定して動かす。move は差分、coords は行き先の座標そのもの。アニメっぽく見せるときは少し動かして update する、という流れ(詳細は追加PDF・ドリル)。
黒板にマグネットを貼る台=Canvas。
move: 「今の場所から右へ10、下へ50」とずらす(相対)。coords: 「中心を (200, 300) に置き直す」(絶対)。※「見える」の基準点=メインウィンドウ上の Canvas 座標系(左上がだいたい (0,0)、右が +x、下が +y)。画像は指定座標が中心になることが多い。
# canv は Canvas のインスタンス、タグ "hero" の画像があるとする
canv.move("hero", 10, 50) # 相対: 右10・下50
canv.coords("hero", 200, 300) # 絶対: 中心を (200,300)
canv.update() # 今の設定で画面を更新
| メソッド | 意味 |
|---|---|
move(タグ, dx, dy) | 相対移動 |
coords(タグ, x, y) | 絶対座標(中心) |
update | 表示を現状に合わせる |
長い攻撃ループや点滅はドリル D08。概念では3語の差だけでよい。
なぜどちらも「画像が動く」ので同じに見える。
NG「相手の座標へ行きたい」のに毎回 move だけで済ませようとして位置が積み上がる/足りない。
正し方ずらすなら move、位置を決め打ちするなら coords。目的で選ぶ。
補足tkinter は png 向き。jpg は非対応、と講義で注意あり。
試験での答え方
なぜ必要か: 本・雑誌・漫画で「タイトルと値段」は共通、「発行月」「巻」は違う。共通を親に置き、子は差分だけ足す。共通表示を親の `display` に任せると、宿題の Book 系が書ける。
**継承**は、親クラスの仕組みを子が引き継ぐこと。**`super()`** は、子の中から**親の同名処理(よくあるのはコンストラクタや display)を呼び出す窓口**。
別名: 継承 / super()。
同じ名前/同じ見た目だと、全部ひとまとめに見えてしまう
名前と住所は家族共通の台帳(親)。自分の趣味欄だけ子が足す。台帳の共通欄を書くときは「親の書き方を呼ぶ」=`super()`。全部を子がゼロから書き直す必要はない。
仕組み(言葉)
子クラスの定義に親を書く(class Comic(Book):)。子の __init__ で親の初期化を呼ばないと、親が持つべき属性が揃わないことがある。display をオーバーライドしつつ super().display() で共通出力を再利用する、というのが第14回の型。
名前と住所は家族共通の台帳(親)。自分の趣味欄だけ子が足す。台帳の共通欄を書くときは「親の書き方を呼ぶ」=super()。全部を子がゼロから書き直す必要はない。
class Book:
def __init__(self, name, price):
self.name = name
def display(self):
print(self.name)
class Comic(Book):
def __init__(self, name, price, vol):
super().__init__(name, price)
self.vol = vol
(display の差分呼び出しと Magazine 全文はドリル D10。)
| 手順 | 子がやること |
|---|---|
| コンストラクタ | super().__init__(…) で共通引数を親へ |
| display | super().display() のあと差分を表示 |
| 呼び出し | 同じ display 名でポリモーフィズム |
Magazine/Comic の全文と指定インスタンスはドリル D10。
なぜ「継承した=親のコンストラクタも自動」と思い込む。
NG子の __init__ で self.name だけ足し、super().__init__ を忘れる。
正し方共通の初期化は super().__init__ で親に渡す(講義の指示どおり)。
補足ポリモーフィズムで同じ関数から display を呼ぶのは D10。
試験での答え方
__init__ と display それぞれで super を使う順。入門カードと同じ正本を、章として通読できるように再掲(薄くしていない)。
変数が「どこまで使えるか」という有効範囲のこと。同じ名前でも、置いた場所が違えば別物として扱われる。
クラスや関数を書くと、見た目同じ v や area が何種類も出てくる。どれが生きているかを見誤ると、「さっき代入したのにエラー」「値が戻らない」が止まらない。スコープを先に押さえると、以降のクラス変数・ポリモーフィズムの説明がつながる。
教室の黒板(みんなから見える場所)と、自分のノート(自分の席だけで見える場所)がある、と考える。ノートに書いた答えは隣の席から見えない。プログラムでも「どの黒板/ノートに書いたか」がスコープ。
v = 10 # ファイル全体で見える側
def printer():
v = 20 # この関数の中だけの別枠
print(v) # → 20
printer()
print(v) # → 10(上の別枠は消えている)
前後比較(コード無し):
| 前 | 後 |
|---|---|
関数の中で v=20 と書いた | その呼び出し中だけ 20 が見える |
関数の外で print(v) | ファイル先頭の 10 のまま(中の枠は消えた) |
※「外」の基準点=その変数を定義した関数ブロックの外。
代入した場所のブロックが、その名前の寿命と見える範囲を決める。関数の中での代入は、その関数専用の枠を作ることが多い。ファイルの先頭(どの def/class にも入っていない場所)での代入は、ファイル全体から名前で参照できる枠になる。
v なので、「1つの箱を上書きしている」と脳が読む。v=20 したから、外の print(v) も 20」と思う。global 宣言で外を書き換える話は発展。講義の基本は「枠が分かれる」理解でよい。ローカルは、ある関数(またはメソッド)のブロックの中だけで生きる変数。グローバルは、ファイルのトップレベル(どの def/class の外でもない場所)で定義された変数で、ファイル全体から名前で参照できる。
面積などの一時計算は、メソッドを出たら捨ててよいことが多い。一方、設定値のようにファイル全体で共有したい値もある。寿命を分けないと、「メソッドを抜けたあと print(area) したらエラー」や「意図せず全体の値を書き換えた」が起きる。
会議中だけのメモ用紙(ローカル)と、共用ホワイトボード(グローバル)。会議が終わるとメモ用紙は捨てるが、ホワイトボードの字は残る。
g = 1 # グローバル
def f():
area = 3.14 * 2 # ローカル(f の中だけ)
print(area)
f()
# print(area) # → エラー(定義した関数ブロックの外からは見えない)
print(g) # → 1
| 種類 | 定義場所 | 定義した関数の外から参照 | 寿命 |
|---|---|---|---|
| ローカル | 関数/メソッドの中 | 不可 | 呼び出しが終わるまで |
| グローバル | ファイル先頭(トップレベル) | 可 | ファイル実行中 |
※「外」の基準点=その変数を定義した関数ブロックの外。
Python は「どこで代入したか」を見て枠を決める。関数の中で代入すると、その関数用の名前表に載る。トップレベルで代入すると、ファイル用の名前表に載る。メソッド内で self. 無しの代入はローカルであり、オブジェクトの属性にはならない。
area = … と書くと、「円の面積をオブジェクトが覚えた」ように見える。self. 無しの area を、あとから c.area で取り出そうとする。area は呼び出し中の一時メモ。オブジェクトに残すなら self.area = …。インスタンス変数は、オブジェクト1つごとに持つデータ(self.名前)。クラス変数は、同じクラスのオブジェクトが共有するデータ(クラス本体に直接書いた変数)。
円ごとに違う半径はインスタンス変数。全円で共通の定数っぽい値やカウンタはクラス変数向き。混ぜると「1つの円を変えたら全部変わった」や「self. を付け忘れてローカルになった」が起きる。
学籍番号は学生一人ひとり違う(インスタンス)。学校名は同じクラス(同じ学校)の全員で同じ札を見るイメージ(クラス変数)。
※「共有」の基準点=同じクラスから作られた各インスタンスのあいだで、クラスに置いた1つの枠を見ている、という意味。
class Circle:
kind = "円" # クラス変数(共有)
def __init__(self, r):
self.r = r # インスタンス変数(個体ごと)
a = Circle(2)
b = Circle(5)
print(a.r, b.r) # → 2 5(別々)
print(a.kind, b.kind) # → 円 円(同じ枠を見ている)
| 種類 | クラス外からの読み方 | クラス内での典型 |
|---|---|---|
| インスタンス変数 | インスタンス.名前 | self.名前 |
| クラス変数 | クラス.名前 または インスタンス.名前(読み出し) | クラス本体に直接定義 |
self.r = … は「今のこのオブジェクト専用の引き出し」にしまう。クラス本体の kind = … は「クラスの共用引き出し」。メソッド内で r = … のように self. 無しだと、それはローカル変数であり、どちらにも残らない。
self. を付け忘れると「変数を書いたつもり」になりやすい。area = 3.14 * self.r ** 2 のあと print(obj.area) で取り出す。self.area = …。付けない area はメソッド終了で消える。インスタンス.名前 = で代入すると個体側に影ができることがある(発展)。self./クラス.)と「誰のものか」を書く。self/共有(基準点付き)。なぜ今この演習か: 概念を言葉で押さえたあと、宿題同型を途中式(完成コード)で一度通すため。
答案文: 「概念は入門・本編、長い実装はドリルで書く」
部分点: 用語の完成文/ドリルの採点語
考察: コード科目では L3 の手数の本体がドリルの worked にある。ここでは飛ばさずハブとして接続する。
入門カードと同じ正本を、章として通読できるように再掲(薄くしていない)。
同じ呼び方(同じメソッド名)で、相手の種類ごとに違う処理をさせる考え方。使う側は「相手が誰か」を細かく分けず、同じ窓口から呼べる。
円も正方形も「面積を求める」なら、使う側は毎回クラス名で分岐したくない。同じ area() というボタンを押せば、中身は相手が勝手にやる——そう書けると、あとから新しい図形を足しても呼び出し側が壊れにくい。
車種が違っても、発進は同じ「Aボタン」。押す動作は同じで、中のエンジンのかかり方は車ごとに違う。使う人は車の内部を知らなくてよい。
前後比較(コード無し):
| 前 | 後 |
|---|---|
| 相手ごとに別関数を呼び分ける | 同じ関数/同じメソッド名に渡す |
| 「円用・正方形用」と分岐だらけ | 窓口は1つ、中身だけ違う |
class Dog:
def speak(self):
return "わん"
class Cat:
def speak(self):
return "にゃ"
def intro(obj):
return obj.speak() # 同じ窓口
print(intro(Dog())) # → わん
print(intro(Cat())) # → にゃ
異なるクラスに同じ名前のメソッドを用意する。呼び出し側は「そのオブジェクトのそのメソッド」を実行するだけなので、渡した相手のクラスに応じて中身が切り替わる。継承+オーバーライドでも同じ形になる(親の型として扱い、子の実装が動く)。
親クラスで定義したメソッドを、子クラスが同じ名前で書き直して上書きすること。
「動物は鳴く」は親で共通に置きたいが、犬は「わんわん」、蛇は「シャー」と変えたい。共通部分は親、違う部分だけ子で上書きすると、重複を減らしつつポリモーフィズムが使える。
会社の「挨拶マニュアル(親)」がある。部署ごとに一言だけ差し替えるのがオーバーライド。マニュアル全体をゼロから別冊にするのではない。
class Animal:
def cry(self):
return "鳴く"
class Dog(Animal):
def cry(self): # 同名で上書き
return "わんわん"
print(Dog().cry()) # → わんわん(親の「鳴く」ではない)
| 用語 | 役割 |
|---|---|
親の cry | 共通の型・デフォルト動作 |
子の cry | 同じ入り口で中身だけ差し替え |
子クラスに親と同じメソッド名があると、そのインスタンスでは子の定義が優先される。呼び出し側は obj.cry() のままでよい(ポリモーフィズムとセットで使う)。
"鳴く" のままなのに「オーバーライドした」と言う。super()(C13/ドリル D10)。なぜ今この演習か: 概念を言葉で押さえたあと、宿題同型を途中式(完成コード)で一度通すため。
答案文: 「概念は入門・本編、長い実装はドリルで書く」
部分点: 用語の完成文/ドリルの採点語
考察: コード科目では L3 の手数の本体がドリルの worked にある。ここでは飛ばさずハブとして接続する。
入門カードと同じ正本を、章として通読できるように再掲(薄くしていない)。
プログラミングの道具セットの階層。ライブラリが大きな道具箱、その中の一つ一つの道具(.py)がモジュール、モジュールをフォルダにまとめたものがパッケージ。
毎回ゼロから乱数や日付を書くのは無駄で、ミスも増える。用意された道具を import して使うと、試験の実装も短く正確になる。階層の名前を取り違えると「何を import すればいいか」が曖昧になる。
工具箱一式=ライブラリ。中のプラスドライバ一本=モジュール。ドライバセットの引き出し(複数モジュール入り)=パッケージ。ねじを締める動作が、モジュール内の関数やクラスのメソッド。
import math
print(math.pi) # モジュール math の定数
from math import sqrt
print(sqrt(9)) # → 3.0
| 用語 | 役割(関係) |
|---|---|
| ライブラリ | モジュール/パッケージの集まり(道具箱全体) |
| モジュール | 1つの .py(1つの道具) |
| パッケージ | 複数モジュールをまとめたディレクトリ |
部品の列挙だけで終わらず、「箱→中の道具→使い方(関数/クラス)」の関係で覚える。
使いたい道具を名前で読み込むと、その中の関数・クラス・定数が使える。標準で付いてくるものと、後から入れるものがある(C08)。
.py(モジュール)名を言えない。math)。ライブラリは「その仲間全体」の呼び名。他のファイル(モジュール)の道具を、今のプログラムに読み込んで名前を付ける書き方。import 全体、from 一部、as は短い別名。
標準ライブラリでも外部でも、読み込まないと使えないものが多い(組み込み関数は例外)。書き方を間違えると NameError や長い名前の打ち間違いが続く。
本棚から本を借りる。
import calendar=本を一冊まるごと借り、読むとき「calendar の ○○」と言う。from calendar import month=必要な章だけコピーして、month と短く呼ぶ。as cal=借りた本に「cal」という付箋名を付ける。import calendar
calendar.month(2026, 7)
import calendar as cal
cal.month(2026, 7)
from calendar import month, isleap
month(2026, 7)
isleap(2024) # → True
| 書き方 | 効果 |
|---|---|
import 名 | 名.関数 で使う |
import 名 as 別名 | 別名.関数 |
from 名 import 部品 | 部品 を直接呼ぶ |
組み込み(例: print)は import 不要。標準モジュールは import が必要——この差が試験のひっかけになりやすい。
import はモジュールの名前空間を今のファイルに結びつける。from はそこから特定の名前だけを今の名前表に取り込む。as は結びつけた名前のラベルを短くするだけ。
from math import sqrt のあと、つい math.sqrt と書いてしまう(またはその逆)。from math import sqrt なのに math.sqrt(9) で呼ぶ。from なら sqrt(9)、import math なら math.sqrt(9)。abs は組み込み、math.fabs はモジュール側(第10回の対比)。標準は Python を入れたときに最初から付いてくる道具(ただしモジュールは import が必要)。外部は別途インストールするもの(例: Pillow)。どちらも使い始めは import。
乱数や数学は標準で足りることが多い。画像処理(Pillow)のように、標準に無い道具は pip install してから使う。区別できないと「なぜエラー?」の切り分けができない。
スマホの初期アプリ=標準。アプリストアから追加したアプリ=外部。どちらも「開いて使う」必要があるが、後者は先にダウンロード(インストール)がいる。
標準(import のみ):
import random
print(random.randint(1, 6))
外部(インストール後):
from PIL import Image
img = Image.open("hana.jpg")
img.show()
| 標準ライブラリ | 外部ライブラリ | |
|---|---|---|
| 入手 | Python 同梱 | pip install など |
| 使用 | import | インストール後に import |
| 例 | random, math, tkinter | Pillow(PIL) |
※ Pillow はパッケージ名と import 名(PIL)が違う点に注意。
標準モジュールは環境にあらかじめある。外部は PyPI などから入れ、そのあと標準と同じく import して関数/クラスを使う。画像なら open でオブジェクトを得て、show や属性(height 等)で操作する。
random.randint を import なしで使う。print, abs 等)だけが import 不要。標準モジュールは import 必要。なぜ今この演習か: 概念を言葉で押さえたあと、宿題同型を途中式(完成コード)で一度通すため。
答案文: 「概念は入門・本編、長い実装はドリルで書く」
部分点: 用語の完成文/ドリルの採点語
考察: コード科目では L3 の手数の本体がドリルの worked にある。ここでは飛ばさずハブとして接続する。
入門カードと同じ正本を、章として通読できるように再掲(薄くしていない)。
Python 標準の GUI(画面付きアプリ)用ツールキット。窓(ウィンドウ)の上にボタンやラベルなどの部品(ウィジェット)を置いて、クリックなどの操作に処理をつなぐ。
期末本線ではチェック/ラジオ/キャンバスなど「画面を作って動かす」問題が出る想定。コンソールの print だけでは足りない。窓の作り方と部品の置き方の型を持っておく必要がある。
紙の工作キット。土台の厚紙がメインウィンドウ、シールがボタンやラベル。シールを貼る=pack などで配置。押したら動く仕組みを紐づける=command。
import tkinter as tk
base = tk.Tk()
btn = tk.Button(base, text="PUSH!!")
btn.pack()
base.mainloop() # 画面を出し続ける
前後比較(コード無し):
| 前 | 後 |
|---|---|
| 部品を作っただけ | まだ画面に並ばない |
pack(など)で配置 | 見える位置に並ぶ |
mainloop | 窓が開いたまま操作を待ち続ける |
Tk で土台の窓を作る。Button や Label など部品クラスでウィジェットを作る(親は土台)。pack 等で並べる。command で関数を結びつける。mainloop で表示を維持する。長い画面(飲料UI・攻撃ボタン一式)はドリル側。
Button(...) だけで pack も mainloop も書かない。side / anchor は配置の微調整(第12回)。画面の部品(入力欄・チェック・ラジオ)と連動する専用の変数オブジェクト。部品の状態が変わると値が変わり、get / set で読み書きする。
普通の Python 変数だけだと、チェックのオンオフや入力文字を部品から取り出しにくい。ウィジェット変数をはさむと、「今チェックされているか」「今選ばれている value」を試験で聞かれても答えられる。
スイッチとランプをつなぐ電線。スイッチ(チェックボタン)を倒すと、電線の先の状態表示(変数)が True/False に変わる。ランプを直接いじるのではなく、電線(変数)を見る。
※「連動/見える」の基準点=そのウィジェット変数を variable / textvariable で結びつけた部品から見た状態。
import tkinter as tk
base = tk.Tk()
bln = tk.BooleanVar()
bln.set(True) # 初期オン
cb = tk.Checkbutton(base, text="ON", variable=bln)
cb.pack()
# あとで: bln.get() → True/False
| クラス | 向き |
|---|---|
StringVar | 文字列(Entry / Label の textvariable) |
BooleanVar | True/False(Checkbutton) |
IntVar | 整数(Radiobutton の value と一致させる) |
部品に variable= や textvariable= でウィジェット変数を渡す。ユーザー操作で部品が変わると変数側も更新される。プログラムから set すれば初期表示も変えられる。状態の取得は get。
x = True とウィジェット変数を同一視する。bool を渡して状態を取ろうとする。get/set で扱う。value が一致したとき選ばれる。どちらも「選ぶ」ための GUI 部品。チェックはグループ内で複数オンにできる。ラジオはグループ内でどれか1つだけ選ぶ。
飲料を複数注文したいならチェック、ランチセットを1つだけ選ぶならラジオ、と用途が違う。変数の型も違う(BooleanVar の並び vs IntVar+value)。取り違えると UI 仕様が宿題と食い違う。
学食の伝票。トッピングをいくつでも付ける=チェック。日替わりA/B/Cはどれか一つ=ラジオ(昔のラジオの押しボタンは1つ押すと他が戻る)。
チェック(複数可):
# bln1, bln2 はそれぞれ BooleanVar
# Checkbutton(..., variable=bln1)
# Checkbutton(..., variable=bln2)
# 両方 True になり得る
ラジオ(1つだけ):
# v = IntVar(); v.set(1)
# Radiobutton(..., variable=v, value=1)
# Radiobutton(..., variable=v, value=2)
# 選ばれているのは v.get() と一致する value の1つ
| チェックボタン | ラジオボタン | |
|---|---|---|
| 同時選択 | 複数可 | グループ内1つ |
| 典型変数 | BooleanVar(部品ごと) | IntVar(グループで共有) |
| 状態の見方 | 各 get() が True/False | 共有変数の get() が value |
チェックは部品ごとにオンオフの枠を持つ。ラジオはグループで1つの IntVar を共有し、各ボタンに違う value を付ける。ユーザーが押すと変数がその value に変わり、一致するボタンだけが選択表示になる。
なぜ今この演習か: 概念を言葉で押さえたあと、宿題同型を途中式(完成コード)で一度通すため。
答案文: 「概念は入門・本編、長い実装はドリルで書く」
部分点: 用語の完成文/ドリルの採点語
考察: コード科目では L3 の手数の本体がドリルの worked にある。ここでは飛ばさずハブとして接続する。
入門カードと同じ正本を、章として通読できるように再掲(薄くしていない)。
Canvas は、線・円・画像・文字を載せる絵を描く台。move は今の位置から相対的にずらす。coords は中心座標を絶対指定で置き直す。
キャラ画像を出したり、攻撃ボタンで相手方向へ動かしたりする宿題の土台。相対移動と絶対移動を混同すると「一回動いたら変な場所に飛ぶ」になる。
黒板にマグネットを貼る台=Canvas。
move: 「今の場所から右へ10、下へ50」とずらす(相対)。coords: 「中心を (200, 300) に置き直す」(絶対)。※「見える」の基準点=メインウィンドウ上の Canvas 座標系(左上がだいたい (0,0)、右が +x、下が +y)。画像は指定座標が中心になることが多い。
# canv は Canvas のインスタンス、タグ "hero" の画像があるとする
canv.move("hero", 10, 50) # 相対: 右10・下50
canv.coords("hero", 200, 300) # 絶対: 中心を (200,300)
canv.update() # 今の設定で画面を更新
| メソッド | 意味 |
|---|---|
move(タグ, dx, dy) | 相対移動 |
coords(タグ, x, y) | 絶対座標(中心) |
update | 表示を現状に合わせる |
長い攻撃ループや点滅はドリル D08。概念では3語の差だけでよい。
create_image などで図形にタグを付ける。あとからタグを指定して動かす。move は差分、coords は行き先の座標そのもの。アニメっぽく見せるときは少し動かして update する、という流れ(詳細は追加PDF・ドリル)。
move だけで済ませようとして位置が積み上がる/足りない。なぜ今この演習か: 概念を言葉で押さえたあと、宿題同型を途中式(完成コード)で一度通すため。
答案文: 「概念は入門・本編、長い実装はドリルで書く」
部分点: 用語の完成文/ドリルの採点語
考察: コード科目では L3 の手数の本体がドリルの worked にある。ここでは飛ばさずハブとして接続する。
入門カードと同じ正本を、章として通読できるように再掲(薄くしていない)。
継承は、親クラスの仕組みを子が引き継ぐこと。super() は、子の中から親の同名処理(よくあるのはコンストラクタや display)を呼び出す窓口。
本・雑誌・漫画で「タイトルと値段」は共通、「発行月」「巻」は違う。共通を親に置き、子は差分だけ足す。共通表示を親の display に任せると、宿題の Book 系が書ける。
名前と住所は家族共通の台帳(親)。自分の趣味欄だけ子が足す。台帳の共通欄を書くときは「親の書き方を呼ぶ」=super()。全部を子がゼロから書き直す必要はない。
class Book:
def __init__(self, name, price):
self.name = name
def display(self):
print(self.name)
class Comic(Book):
def __init__(self, name, price, vol):
super().__init__(name, price)
self.vol = vol
(display の差分呼び出しと Magazine 全文はドリル D10。)
| 手順 | 子がやること |
|---|---|
| コンストラクタ | super().__init__(…) で共通引数を親へ |
| display | super().display() のあと差分を表示 |
| 呼び出し | 同じ display 名でポリモーフィズム |
Magazine/Comic の全文と指定インスタンスはドリル D10。
子クラスの定義に親を書く(class Comic(Book):)。子の __init__ で親の初期化を呼ばないと、親が持つべき属性が揃わないことがある。display をオーバーライドしつつ super().display() で共通出力を再利用する、というのが第14回の型。
__init__ で self.name だけ足し、super().__init__ を忘れる。super().__init__ で親に渡す(講義の指示どおり)。display を呼ぶのは D10。__init__ と display それぞれで super を使う順。なぜ今この演習か: 概念を言葉で押さえたあと、宿題同型を途中式(完成コード)で一度通すため。
答案文: 「概念は入門・本編、長い実装はドリルで書く」
部分点: 用語の完成文/ドリルの採点語
考察: コード科目では L3 の手数の本体がドリルの worked にある。ここでは飛ばさずハブとして接続する。
①完成例(worked)は下の各ドリルと本編 L3。②フェード(faded)は穴埋め。③自力(solo)は白紙でノートに書く。L3 と同数値・同文言のコピペ禁止(L4 は別 surface)。
正本: runs/ool-final/content/drills/*.md → ドリル一覧へ
正本は runs/ool-final/content/drills/*.md。各テーマ: 与件→求めよ→worked→fade→solo。
| ID | テーマ | リンク |
|---|---|---|
| D01 | Circle/Square | 開く |
| D02 | Animal | 開く |
| D03 | サイコロ | 開く |
| D04 | time.sleep | 開く |
| D04b | Pillow | 開く |
| D05 | mondai | 開く |
| D06 | Checkbutton | 開く |
| D07 | Radiobutton | 開く |
| D08 | 攻撃 Canvas | 開く |
| D09 | おみくじ | 開く |
| D10 | Book 系 | 開く |
クラス定義と Canvas 攻撃は ドリル⑧ に統合(MD: D08)。
資料準拠: 第9回 練習問題1(OOL_6月16日)
CircleArea: コンストラクタ引数 r(半径)。area メソッドで円面積 cc を返す。SquareArea: コンストラクタ引数 a(一辺)。area メソッドで正方形面積 ss を返す。cal_area 関数から area を呼べるようにする(引数は自由)。上記3クラス/関数を実装し、円・正方形それぞれで cal_area 経由の面積が得られること。
この問題の答案型(骨格)
class CircleArea:
def __init__(self, r):
def area(self):
class SquareArea:
def __init__(self, a):
def area(self):
def cal_area(obj):
class CircleArea:
def __init__(self, r):
self.r = r
def area(self):
cc = 3.14 * self.r * self.r
return cc
class SquareArea:
def __init__(self, a):
self.a = a
def area(self):
ss = self.a * self.a
return ss
def cal_area(obj):
return obj.area()
print(cal_area(CircleArea(2)))
print(cal_area(SquareArea(3)))
area を持つ2クラス+共通呼び出し関数。3.14*r*r(講義例に合わせる)、正方形 a*a。__init__ で self.r、area で計算して返す。self.a。def cal_area(obj): return obj.area()。class CircleArea:
def __init__(self, r):
# TODO: self.r
pass
def area(self):
# TODO: cc を return
pass
class SquareArea:
def __init__(self, a):
self.a = a
def area(self):
return self.a * self.a
def cal_area(obj):
return obj.area()
ヒント: `cal_area` と `SquareArea` は埋まっている。`CircleArea` の `__init__` と `area` だけ書け。
class CircleArea:
def __init__(self, r):
self.r = r
def area(self):
cc = 3.14 * self.r * self.r
return cc
class SquareArea:
def __init__(self, a):
self.a = a
def area(self):
ss = self.a * self.a
return ss
def cal_area(obj):
return obj.area()
print(cal_area(CircleArea(2)))
print(cal_area(SquareArea(3)))与件どおり白紙で書け。円 r=5、正方形 a=4 で cal_area の結果を示せ。
class CircleArea:
def __init__(self, r):
self.r = r
def area(self):
cc = 3.14 * self.r * self.r
return cc
class SquareArea:
def __init__(self, a):
self.a = a
def area(self):
ss = self.a * self.a
return ss
def cal_area(obj):
return obj.area()
print(cal_area(CircleArea(2)))
print(cal_area(SquareArea(3)))資料準拠: 第9回 演習問題1(OOL_6月16日)※第10回冒頭にも再掲
Animal: cry が "鳴く" を返す。Dog: cry が "わんわん"。Snake: cry が "シャー"。cry をポリモーフィズムの考えで実行する。継承+オーバーライド+共通関数(または同名呼び出し)で、Dog/Snake の鳴き声を得ること。
この問題の答案型(骨格)
class Animal:
def cry(self):
class Dog(Animal):
def cry(self):
class Snake(Animal):
def cry(self):
def play(animal):
class Animal:
def cry(self):
return "鳴く"
class Dog(Animal):
def cry(self):
return "わんわん"
class Snake(Animal):
def cry(self):
return "シャー"
def play(animal):
return animal.cry()
print(play(Dog()))
print(play(Snake()))
def play(a): return a.cry() → Dog/Snake を渡す。class Animal:
def cry(self):
return "鳴く"
class Dog(Animal):
def cry(self):
return "わんわん"
class Snake(Animal):
def cry(self):
pass # TODO
def play(animal):
pass # TODO
ヒント: 親と Dog は完成。Snake の `cry` と `play` の中身だけ埋めよ。
class Animal:
def cry(self):
return "鳴く"
class Dog(Animal):
def cry(self):
return "わんわん"
class Snake(Animal):
def cry(self):
return "シャー"
def play(animal):
return animal.cry()
print(play(Dog()))
print(play(Snake()))与件どおり白紙実装。play(Dog()) と play(Snake()) の表示結果を書け。
class Animal:
def cry(self):
return "鳴く"
class Dog(Animal):
def cry(self):
return "わんわん"
class Snake(Animal):
def cry(self):
return "シャー"
def play(animal):
return animal.cry()
print(play(Dog()))
print(play(Snake()))資料準拠: 第9回 演習問題2(OOL_6月16日)
random で 1〜6 の整数を2つ(di1, di2)。math モジュールを使うこと。上記仕様の短プログラム。
この問題の答案型(骨格)
import random
import math
import random
import math
di1 = random.randint(1, 6)
di2 = random.randint(1, 6)
print(di1, di2)
if di1 == di2:
print("同じ数")
else:
print(math.fabs(di1 - di2))
random.randint(1,6)、math.fabs(di1-di2)(講義指定)。import random
import math
di1 = random.randint(1, 6)
di2 = random.randint(1, 6)
# TODO: 一致/差
ヒント: 乱数取得まで埋まっている。比較と表示だけ書け。
import random
import math
di1 = random.randint(1, 6)
di2 = random.randint(1, 6)
print(di1, di2)
if di1 == di2:
print("同じ数")
else:
print(math.fabs(di1 - di2))白紙。実行例として「同じ数」になる場合と差が出る場合の表示イメージを1つずつ書け。
import random
import math
di1 = random.randint(1, 6)
di2 = random.randint(1, 6)
print(di1, di2)
if di1 == di2:
print("同じ数")
else:
print(math.fabs(di1 - di2))資料準拠: 第10回 練習問題1(OOL_6月23日)
time モジュールを使う。time.sleep(秒数) で 3 秒待機。待機前後の time.time() の差が約3になるプログラム。
この問題の答案型(骨格)
import time
import time
t0 = time.time()
time.sleep(3)
t1 = time.time()
print(t1 - t0)
time.time(), time.sleep(3)。import time
# TODO: t0
time.sleep(3)
# TODO: t1 と差
ヒント: `sleep(3)` は既にある。`t0`/`t1` の取得と差の表示だけ書け。
import time
t0 = time.time()
time.sleep(3)
t1 = time.time()
print(t1 - t0)白紙で書け。差がおおよそ 3 前後になる理由を一文で添えよ。
import time
t0 = time.time()
time.sleep(3)
t1 = time.time()
print(t1 - t0)資料準拠: 第10回(OOL_6月23日)Pillow 導入部
from PIL import Imagehana.jpg)を Image.open で開き show するheight(または size)など属性を1つ表示する※ 長い回転・合成チェーンは本ドリルの必須外(概念は玩具、詳細は宿題ノート)。
open → show → 属性表示の最小3行+import。
この問題の答案型(骨格)
1. 求めるもの: 画像オブジェクトを得て表示し、属性を読む。
2. 使うもの: `PIL.Image`。
3. 手順: import → open → show → print 属性。
from PIL import Image
img = Image.open("hana.jpg")
img.show()
print(img.height)
from PIL import Image
img = Image.open("hana.jpg")
img.show()
print(img.height)
PIL.Image。from PIL import Image
img = Image.open("hana.jpg")
# TODO
ヒント: `open` まで埋まっている。`show` と属性表示だけ書け。
from PIL import Image
img = Image.open("hana.jpg")
img.show()
print(img.height)白紙。Pillow が外部ライブラリである理由(pip)を一文添えよ。
from PIL import Image
img = Image.open("hana.jpg")
img.show()
print(img.height)資料準拠: 第10回 演習問題(OOL_6月23日)/第12回冒頭再掲
mondai 関数を作る。mondai 関数+10回ループ+開始/終了時刻。
この問題の答案型(骨格)
import random
import time
def mondai():
import random
import time
def mondai():
n1 = random.randint(1, 10)
n2 = random.randint(1, 10)
ans = int(input(f"{n1}+{n2}= "))
if ans == n1 + n2:
print("正解です")
else:
print("不正解です")
t0 = time.time()
for _ in range(10):
mondai()
t1 = time.time()
print("かかった時間:", t1 - t0)
random.randint, input, time.time。import random
import time
def mondai():
n1 = random.randint(1, 10)
n2 = random.randint(1, 10)
ans = int(input(f"{n1}+{n2}= "))
print("正解です" if ans == n1 + n2 else "不正解です")
# TODO: 計測つきで10回
ヒント: `mondai` の中身は埋まっている。10回ループと時間計測だけ書け。
import random
import time
def mondai():
n1 = random.randint(1, 10)
n2 = random.randint(1, 10)
ans = int(input(f"{n1}+{n2}= "))
if ans == n1 + n2:
print("正解です")
else:
print("不正解です")
t0 = time.time()
for _ in range(10):
mondai()
t1 = time.time()
print("かかった時間:", t1 - t0)白紙。関数化せずに10回コピペしたコードとの違い(なぜ関数か)を一文で書け。
import random
import time
def mondai():
n1 = random.randint(1, 10)
n2 = random.randint(1, 10)
ans = int(input(f"{n1}+{n2}= "))
if ans == n1 + n2:
print("正解です")
else:
print("不正解です")
t0 = time.time()
for _ in range(10):
mondai()
t1 = time.time()
print("かかった時間:", t1 - t0)資料準拠: 第12回 練習問題1・2(OOL_6月30日)
for+辞書で書き直す。BooleanVar×3(または for 生成)+表示用 Label/ボタン。
この問題の答案型(骨格)
import tkinter as tk
def show():
import tkinter as tk
base = tk.Tk()
drink = {0: "コーヒー", 1: "お茶", 2: "ジュース"}
vars_ = []
for i in range(len(drink)):
v = tk.BooleanVar()
vars_.append(v)
tk.Checkbutton(base, text=drink[i], variable=v).pack(anchor=tk.W)
msg = tk.StringVar(value="")
tk.Label(base, textvariable=msg).pack()
def show():
picked = [drink[i] for i in range(len(drink)) if vars_[i].get()]
msg.set(", ".join(picked) if picked else "(未選択)")
tk.Button(base, text="決定", command=show).pack()
base.mainloop()
BooleanVar, Checkbutton, Button, Label, 辞書+for。# drink, vars_ は生成済みとする
def show():
pass # TODO: get して msg.set
ヒント: 辞書と Checkbutton の for は埋まっている。`show` だけ書け。
import tkinter as tk
base = tk.Tk()
drink = {0: "コーヒー", 1: "お茶", 2: "ジュース"}
vars_ = []
for i in range(len(drink)):
v = tk.BooleanVar()
vars_.append(v)
tk.Checkbutton(base, text=drink[i], variable=v).pack(anchor=tk.W)
msg = tk.StringVar(value="")
tk.Label(base, textvariable=msg).pack()
def show():
picked = [drink[i] for i in range(len(drink)) if vars_[i].get()]
msg.set(", ".join(picked) if picked else "(未選択)")
tk.Button(base, text="決定", command=show).pack()
base.mainloop()練習1(手書き3回)版を先に書き、練習2(for)版にリファクタせよ。
import tkinter as tk
base = tk.Tk()
drink = {0: "コーヒー", 1: "お茶", 2: "ジュース"}
vars_ = []
for i in range(len(drink)):
v = tk.BooleanVar()
vars_.append(v)
tk.Checkbutton(base, text=drink[i], variable=v).pack(anchor=tk.W)
msg = tk.StringVar(value="")
tk.Label(base, textvariable=msg).pack()
def show():
picked = [drink[i] for i in range(len(drink)) if vars_[i].get()]
msg.set(", ".join(picked) if picked else "(未選択)")
tk.Button(base, text="決定", command=show).pack()
base.mainloop()資料準拠: 第12回 演習問題(OOL_6月30日)/第13回冒頭再掲
for を使う。IntVar 共有+value 付き Radiobutton を for で生成。選択値の表示ができればなおよい。
この問題の答案型(骨格)
import tkinter as tk
def show():
import tkinter as tk
base = tk.Tk()
menu = {0: "Aランチ", 1: "Bランチ", 2: "Cランチ"}
v = tk.IntVar(value=0)
for i in range(len(menu)):
tk.Radiobutton(base, text=menu[i], variable=v, value=i).pack(anchor=tk.W)
msg = tk.StringVar()
tk.Label(base, textvariable=msg).pack()
def show():
msg.set(menu[v.get()])
tk.Button(base, text="決定", command=show).pack()
base.mainloop()
IntVar, Radiobutton, 辞書/リスト+for。# TODO from Fade section
ヒント: Radiobutton の for は完成。`show` と初期 `value` の意味をコメントで説明しつつ `show` を実装せよ。
import tkinter as tk
base = tk.Tk()
menu = {0: "Aランチ", 1: "Bランチ", 2: "Cランチ"}
v = tk.IntVar(value=0)
for i in range(len(menu)):
tk.Radiobutton(base, text=menu[i], variable=v, value=i).pack(anchor=tk.W)
msg = tk.StringVar()
tk.Label(base, textvariable=msg).pack()
def show():
msg.set(menu[v.get()])
tk.Button(base, text="決定", command=show).pack()
base.mainloop()白紙。チェックボタン版との違い(変数が1つか複数か)を答案に一文書け。
import tkinter as tk
base = tk.Tk()
menu = {0: "Aランチ", 1: "Bランチ", 2: "Cランチ"}
v = tk.IntVar(value=0)
for i in range(len(menu)):
tk.Radiobutton(base, text=menu[i], variable=v, value=i).pack(anchor=tk.W)
msg = tk.StringVar()
tk.Label(base, textvariable=msg).pack()
def show():
msg.set(menu[v.get()])
tk.Button(base, text="決定", command=show).pack()
base.mainloop()資料準拠: 第13回 練習1・演習(OOL_7月7日)+ OOL_7月7日追加.pdf/第14回冒頭
GameCharacter クラス: コンストラクタでジョブとライフ。info でジョブとライフを表示。例: 騎士 life=120、魔法使 life=80。
move 等。追加資料の流れ)。途中まででも提出可、と講義にあるが、本ドリルは worked まで完成形を示す。
クラス+Canvas 配置+攻撃で相対移動する最小実装。
この問題の答案型(骨格)
import tkinter as tk
class GameCharacter:
def __init__(self, job, life):
def info(self):
def attack_left():
def attack_right():
import tkinter as tk
class GameCharacter:
def __init__(self, job, life):
self.job = job
self.life = life
def info(self):
print(self.job, self.life)
# --- GUI(画像ファイルは教材の png を同じフォルダに置く)---
base = tk.Tk()
canv = tk.Canvas(base, width=400, height=300)
canv.pack()
# 実際の試験/宿題では PhotoImage で png を読む
# img_l = tk.PhotoImage(file="knight.png")
# img_r = tk.PhotoImage(file="wizard.png")
# canv.create_image(100, 150, image=img_l, tags=("left",))
# canv.create_image(300, 150, image=img_r, tags=("right",))
def attack_left():
# 左キャラを右方向へ寄せる(相対)
for _ in range(10):
canv.move("left", 8, 0)
canv.update()
def attack_right():
for _ in range(10):
canv.move("right", -8, 0)
canv.update()
tk.Button(base, text="左が攻撃", command=attack_left).pack(side=tk.LEFT)
tk.Button(base, text="右が攻撃", command=attack_right).pack(side=tk.LEFT)
c1 = GameCharacter("騎士", 120)
c2 = GameCharacter("魔法使", 80)
c1.info()
c2.info()
base.mainloop()
Canvas.create_image、タグ、move、update。※ 画像読み込み行は環境依存のためコメント例。手元ではコメントを外す。点滅ダメージは第14回の発展(任意)。
# TODO from Fade section
ヒント: `GameCharacter` と Canvas 配置は完成。`attack_left` だけ `move`+`update` で埋めよ。
import tkinter as tk
class GameCharacter:
def __init__(self, job, life):
self.job = job
self.life = life
def info(self):
print(self.job, self.life)
# --- GUI(画像ファイルは教材の png を同じフォルダに置く)---
base = tk.Tk()
canv = tk.Canvas(base, width=400, height=300)
canv.pack()
# 実際の試験/宿題では PhotoImage で png を読む
# img_l = tk.PhotoImage(file="knight.png")
# img_r = tk.PhotoImage(file="wizard.png")
# canv.create_image(100, 150, image=img_l, tags=("left",))
# canv.create_image(300, 150, image=img_r, tags=("right",))
def attack_left():
# 左キャラを右方向へ寄せる(相対)
for _ in range(10):
canv.move("left", 8, 0)
canv.update()
def attack_right():
for _ in range(10):
canv.move("right", -8, 0)
canv.update()
tk.Button(base, text="左が攻撃", command=attack_left).pack(side=tk.LEFT)
tk.Button(base, text="右が攻撃", command=attack_right).pack(side=tk.LEFT)
c1 = GameCharacter("騎士", 120)
c2 = GameCharacter("魔法使", 80)
c1.info()
c2.info()
base.mainloop()与件の表どおりインスタンスを作り info。続けて攻撃ボタン用の move ループを書け。
import tkinter as tk
class GameCharacter:
def __init__(self, job, life):
self.job = job
self.life = life
def info(self):
print(self.job, self.life)
# --- GUI(画像ファイルは教材の png を同じフォルダに置く)---
base = tk.Tk()
canv = tk.Canvas(base, width=400, height=300)
canv.pack()
# 実際の試験/宿題では PhotoImage で png を読む
# img_l = tk.PhotoImage(file="knight.png")
# img_r = tk.PhotoImage(file="wizard.png")
# canv.create_image(100, 150, image=img_l, tags=("left",))
# canv.create_image(300, 150, image=img_r, tags=("right",))
def attack_left():
# 左キャラを右方向へ寄せる(相対)
for _ in range(10):
canv.move("left", 8, 0)
canv.update()
def attack_right():
for _ in range(10):
canv.move("right", -8, 0)
canv.update()
tk.Button(base, text="左が攻撃", command=attack_left).pack(side=tk.LEFT)
tk.Button(base, text="右が攻撃", command=attack_right).pack(side=tk.LEFT)
c1 = GameCharacter("騎士", 120)
c2 = GameCharacter("魔法使", 80)
c1.info()
c2.info()
base.mainloop()資料準拠: 第14回 練習問題1(OOL_7月14日)
update や Label の text 変更)。ボタン1つ+結果表示が変わる最小おみくじ。
この問題の答案型(骨格)
import tkinter as tk
import random
def draw():
import tkinter as tk
import random
base = tk.Tk()
base.geometry("300x200")
results = ["大吉", "吉", "中吉", "小吉", "凶"]
msg = tk.StringVar(value="ボタンを押しておみくじ")
tk.Label(base, textvariable=msg, font=("", 16)).pack(pady=20)
def draw():
msg.set(random.choice(results))
base.update()
tk.Button(base, text="おみくじを引く", command=draw).pack()
base.mainloop()
random.choice, Button, Label(または Canvas テキスト)。# TODO from Fade section
ヒント: `results` と Button はある。`draw` の中だけ書け。
import tkinter as tk
import random
base = tk.Tk()
base.geometry("300x200")
results = ["大吉", "吉", "中吉", "小吉", "凶"]
msg = tk.StringVar(value="ボタンを押しておみくじ")
tk.Label(base, textvariable=msg, font=("", 16)).pack(pady=20)
def draw():
msg.set(random.choice(results))
base.update()
tk.Button(base, text="おみくじを引く", command=draw).pack()
base.mainloop()白紙。Label の text を直接書き換える書き方と StringVar の違いを一文。
import tkinter as tk
import random
base = tk.Tk()
base.geometry("300x200")
results = ["大吉", "吉", "中吉", "小吉", "凶"]
msg = tk.StringVar(value="ボタンを押しておみくじ")
tk.Label(base, textvariable=msg, font=("", 16)).pack(pady=20)
def draw():
msg.set(random.choice(results))
base.update()
tk.Button(base, text="おみくじを引く", command=draw).pack()
base.mainloop()資料準拠: 第14回 練習問題2(OOL_7月14日)
2-1 Book(name, price) + display(タイトルと値段)。 2-2 Magazine(Book): 引数にキーワード・発行月。親コンストラクタ呼び出し。display は親を呼んだあと差分。 2-3 Comic(Book): キーワード・巻。同様。 2-4 インスタンス:
最後に同じ関数から display をポリモーフィズムで実行。
継承+super+共通関数からの display。
この問題の答案型(骨格)
class Book:
def __init__(self, name, price):
def display(self):
class Magazine(Book):
def __init__(self, name, price, keyword, month):
def display(self):
class Comic(Book):
def __init__(self, name, price, keyword, vol):
def display(self):
def show(obj):
class Book:
def __init__(self, name, price):
self.name = name
self.price = price
def display(self):
print(self.name, self.price)
class Magazine(Book):
def __init__(self, name, price, keyword, month):
super().__init__(name, price)
self.keyword = keyword
self.month = month
def display(self):
super().display()
print(self.keyword, self.month)
class Comic(Book):
def __init__(self, name, price, keyword, vol):
super().__init__(name, price)
self.keyword = keyword
self.vol = vol
def display(self):
super().display()
print(self.keyword, self.vol)
def show(obj):
obj.display()
m1 = Magazine("月刊釣り名人", 1000, "釣りスポット", "8月号")
c1 = Comic("名探偵コナン", 500, "推理もの", "10巻")
show(m1)
show(c1)
super().__init__ / super().display()、ポリモーフィズム。def show(b): b.display()。# TODO from Fade section
ヒント: `Book` と `Magazine` は完成。`Comic` の `__init__` / `display` と `show` だけ書け。引数は与件どおり。
class Book:
def __init__(self, name, price):
self.name = name
self.price = price
def display(self):
print(self.name, self.price)
class Magazine(Book):
def __init__(self, name, price, keyword, month):
super().__init__(name, price)
self.keyword = keyword
self.month = month
def display(self):
super().display()
print(self.keyword, self.month)
class Comic(Book):
def __init__(self, name, price, keyword, vol):
super().__init__(name, price)
self.keyword = keyword
self.vol = vol
def display(self):
super().display()
print(self.keyword, self.vol)
def show(obj):
obj.display()
m1 = Magazine("月刊釣り名人", 1000, "釣りスポット", "8月号")
c1 = Comic("名探偵コナン", 500, "推理もの", "10巻")
show(m1)
show(c1)与件の m1/c1 を白紙実装。答案に「親の display を呼ぶ理由」を一文。
class Book:
def __init__(self, name, price):
self.name = name
self.price = price
def display(self):
print(self.name, self.price)
class Magazine(Book):
def __init__(self, name, price, keyword, month):
super().__init__(name, price)
self.keyword = keyword
self.month = month
def display(self):
super().display()
print(self.keyword, self.month)
class Comic(Book):
def __init__(self, name, price, keyword, vol):
super().__init__(name, price)
self.keyword = keyword
self.vol = vol
def display(self):
super().display()
print(self.keyword, self.vol)
def show(obj):
obj.display()
m1 = Magazine("月刊釣り名人", 1000, "釣りスポット", "8月号")
c1 = Comic("名探偵コナン", 500, "推理もの", "10巻")
show(m1)
show(c1)初出の本説明は入門カード。ここは索引。主役はコーディングドリル。
| 用語 | 一文 | 手がかり |
|---|---|---|
| スコープ | 変数が有効に使える範囲 | ローカル vs グローバル |
| ローカル変数 | 関数ブロック内だけで生きる変数 | 関数を抜けると消える |
| グローバル変数 | ファイル先頭レベルで定義される変数 | ファイル全体で参照可 |
| インスタンス変数 | self. で持つ、個体ごとのデータ | self.job |
| クラス変数 | クラス全体で共有するデータ | クラス名.変数 |
| ポリモーフィズム | 同じ操作名で型ごとに違う処理を呼び出せること | obj.cry() |
| オーバーライド | 親の同名メソッドを子で上書きすること | Dog.cry |
| 標準ライブラリ | Python同梱で import して使う道具箱 | random, math, calendar |
| 外部ライブラリ | pip 等で追加インストールする道具箱 | Pillow |
| モジュール | 拡張子 .py の道具ファイル | import math |
| パッケージ | 複数モジュールをまとめたディレクトリ | from tkinter import … |
| Pillow / PIL | 画像を開く・変形する外部ライブラリ | from PIL import Image |
| tkinter | 標準の GUI ライブラリ | Tk, Button, Label |
| ウィジェット | 画面に置く部品(Button 等) | pack で配置 |
| pack | ウィジェットを上下左右に並べる配置法 | side=LEFT |
| StringVar | Entry 等と連動する文字列ウィジェット変数 | moji.get() |
| BooleanVar | チェックの有無を持つ真偽ウィジェット変数 | bln.set(True) |
| IntVar | ラジオの value を持つ整数ウィジェット変数 | int_v.get() |
| Canvas | 図形・画像を描く描画面 | create_image |
| PhotoImage | tkinter で PNG 等を扱う画像オブジェクト | jpg 非対応 |
| move / coords | Canvas 上の相対移動 / 絶対座標設定 | 攻撃アニメ |
| update | 描画をその時点で画面に反映する | 移動の直後に呼ぶ |
| 継承 | 親クラスの機能を子が引き継ぐこと | class Comic(Book) |
| super() | 親クラスのメソッドを子から呼ぶ仕組み | super().__init__ |
自信度つき。高自信で誤答したトピックは間違いノートへ。コード手書きは演習ドリル優先。
まだなし。診断の高自信誤答が溜まる。
| ID | 内容 | 判定 | メモ |
|---|---|---|---|
| L1 | 第1回講義PDF | out-of-scope | 資料未入手。中間サイトのゼロ起点で代替可 |
| L2-7-mid | 第2–7回(中間範囲) | covered | 本線外。入門要約+https://ool-midterm.pages.dev/ へ誘導 |
| L8 | 第8回(6/9・中間試験日の可能性大) | out-of-scope | 講義PDFなし。中間試験日と推定 |
| L9 | 第9回 スコープ・ポリモーフィズム・標準ライブラリ | covered | core-scope |
| L10 | 第10回 Pillow・外部ライブラリ | covered | core-lib |
| L11 | 第11回 | out-of-scope | 休講想定のため out-of-scope / 欠番 |
| L12 | 第12回 tkinter 基礎 | covered | core-tkinter |
| L13 | 第13回 Canvas・GameCharacter | covered | core-canvas |
| L13-add | 7月7日追加(攻撃動作) | covered | core-canvas |
| L14 | 第14回 ゲーム復習・おみくじ・Book継承 | covered | core-book |
| hw-poly | 宿題 Animal/Dog/Snake ポリモーフィズム | covered | drill-animal |
| hw-circle-square | 宿題 CircleArea/SquareArea+cal_area | covered | drill-circle-square |
| hw-dice | 宿題 サイコロ2個+math.fabs | covered | drill-dice |
| hw-pillow | 宿題 Pillow 画像操作 | covered | drill-pillow |
| hw-mondai | 宿題 mondai関数10回計測 | covered | drill-mondai |
| hw-tk | 宿題 tkinter チェック/ラジオ・for辞書 | covered | drill-check |
| hw-canvas | 宿題 Canvas攻撃ボタン | covered | drill-attack |
| hw-book | 宿題 Book/Magazine/Comic | covered | drill-book |
| hw-omikuji | 宿題 おみくじアプリ | covered | drill-omikuji |