クラスとオブジェクト
学生の名前と点数を一件だけ扱うなら二つの変数で足りる.同じ形の学生を何件も作り,各学生の点数を更新する操作もまとめたくなったとき,クラスが役に立つ.
クラス定義とインスタンス
知識
クラス(class)は属性と操作をまとめた型です.インスタンス(instance)はクラスを呼び出して作った個々の値です.__init__ はインスタンス生成時に呼ばれ,self.name のような属性を設定します.同じクラスから作った二つのインスタンスは,通常それぞれ別の属性を持つ.
身近な例として,学生証の共通書式がクラスであり,名前を書き込んだ一枚一枚の学生証がインスタンスです.書式は共通でも,甲さんの学生証の名前を変えても乙さんの名前は変わりません.
class は「分類・組」を意味する英語です.instance は「一つの事例」を表します.関連語は object(オブジェクト,個々の対象)です.発表では “This class creates student objects” といいます.
class Student:
def __init__(self, name):
self.name = name
a = Student('A')
b = Student('B')
print(a.name, b.name)
a.name = 'C'
print(b.name)ヒントを見る
このコードでは a、b の値を追ってください。インスタンスごとの属性と、クラスに共通する定義を区別します。別のインスタンスを作った場合に、どの値が独立して変わるかを確認します。
演習の解説を見る
Student('A') は一件目を作り,__init__ の name に 'A' を渡す.self.name はその一件目の属性となります.b は別の一件なので,a.name を変えても b.name は 'B' のままです.
A B B
class Student:
def ___(self, name):
___.name = nameヒントを見る
最初の空欄はインスタンス作成時の初期化メソッド名、次はそのインスタンス自身を表す引数名です。
演習の解説を見る
順に __init__,self です.__init__ の前後の下線はそれぞれ二つです.引数 name は呼び出し中だけの変数,self.name は作ったインスタンスの属性です.
一行ずつ追う・比べる
class Student: では共通の型を定義するだけで,学生の実物はまだません.def __init__(self, name): は生成時の処理を定めます.self.name = name は渡された名前を,今作っている学生の属性へ保存します.a = Student('A') ではじめて一件目ができ,b = Student('B') で別の一件ができます.だから出力は A B,続いて B です.
| 名前 | 何を表すか |
|---|---|
Student |
共通の型・設計図. |
a,b |
別々のインスタンス. |
name |
初期化のときだけ渡される引数. |
self.name |
特定の一件に保存される属性. |
よくある誤りは name = name と書いて保存したつもりになることです.左側も関数内の名前なので,インスタンスには残りません.self.name = name と書きます.また a = b は新しい学生を作らず同じ学生への別名を作ります.二件必要なら Student(...) を二回呼ぶ.
メソッドと self
知識
メソッド(method)はクラスの中で定義し,インスタンスを通して呼ぶ関数です.c.add() の呼び出しでは,呼び出し元の c が self に渡されます.そのため self.value += 1 は c の状態を更新します.
身近な例として,カウンターの本体には数字が書かれ,横に「一つ増やす」ボタンが付いていると考えよう.ボタンがメソッドです.self は「今ボタンを押したこのカウンター」を示します.別のカウンターの数字は動きません.
method は「方法・手順」という意味です.self は「自分自身」で,関連語は attribute(属性)です.発表では “The add method updates this instance” といいます.
class Counter:
def __init__(self):
self.value = 0
def add(self):
self.value += 1
c = Counter()
c.add()
c.add()
print(c.value)ヒントを見る
このコードでは c の値を追ってください。インスタンスごとの属性と、クラスに共通する定義を区別します。別のインスタンスを作った場合に、どの値が独立して変わるかを確認します。
演習の解説を見る
生成直後は 0.一回目の add で 1,二回目で 2 となります.self.value += 1 は self.value = self.value + 1 の省略形です.
2
def add(self):
___.value += 1ヒントを見る
value はこのメソッドを呼んだインスタンスの属性です。第1引数を使って、変更する相手を指定します。値を返す行ではありません。
演習の解説を見る
self を入れます.value += 1 とすると,インスタンスの属性ではなく,関数内に存在しない局所変数を読もうとしてエラーになります.
状態の変化を一行ずつ追う
c = Counter() の直後に c.value は0です.一回目の c.add() は c を self として実行し,値を1へ変えます.二回目も同じインスタンスを更新するため2になります.この状態はメソッドを抜けても c に残る.
| 実行直後 | c.value |
d.value |
|---|---|---|
| 二つの Counter を生成 | 0 | 0 |
c.add() |
1 | 0 |
もう一度 c.add() |
2 | 0 |
ここで d = Counter() を追加したと考えます.c.add() では d.value は0のままです.self は「どのカウンターのボタンを押したか」を示す目印です.
c.add(c) と書くと self を二度渡したことになります.通常の呼び出しは c.add() です.定義には self が必要だが,インスタンスから呼ぶときは Python が対応付ける.
継承と上書き
知識
継承(inheritance)は既存のクラスを基に子クラスを定義する仕組みです.子に同名のメソッドを定義すると,親の実装より子の実装が選ばれます.これをオーバーライド(override,上書き)といいます.継承は「子は親の一種」と説明できる関係で使います.
身近な例として,「動物は声を出す」という共通の約束があるとします.猫は動物の一種で,猫らしい声を出します.猫を作るときは動物という土台を受け継ぎ,「声を出す」部分だけ猫用に変えられます.
inheritance は「受け継ぐこと」に由来します.override は「上から覆う」に由来します.関連語は parent class(親クラス)と child class(子クラス)です.発表では “Cat overrides Animal’s speak method” といいます.
class Animal:
def speak(self):
return '声'
class Cat(Animal):
def speak(self):
return 'にゃー'
print(Animal().speak())
print(Cat().speak())ヒントを見る
子クラスに同名のメソッドがある場合と、親からそのまま受け継ぐ場合を分けます。呼び出すインスタンスの型から使う定義を追います。
演習の解説を見る
Animal() では親のメソッドを使います.Cat() では同名の子のメソッドが選ばれます.子の speak を消せば,親から受け継いだ speak により 声 が返る.
声 にゃー
単にコードを再利用したいという理由だけで継承すると,親子関係が不自然になります.例えば「学生が名前を持つ」ことだけを理由に Student を Name の子にしません.
class Cat(___):
def speak(self):
return 'にゃー'ヒントを見る
括弧内には、Cat が機能を受け継ぐ既存の親クラス名を置きます。子クラス自身の名前ではありません。
演習の解説を見る
Animal を入れます.丸括弧内が継承元です.
どのメソッドが実行されるか
class Animal: で親を定義し,class Cat(Animal): で猫を動物の子として定義します.Animal().speak() では親の speak を実行し「声」を返します.Cat().speak() では Cat 側に同名のメソッドがあるので「にゃー」を返します.猫側を削ると親のメソッドが使われます.
| 呼び出し | 選ばれる定義 | 結果 |
|---|---|---|
Animal().speak() |
Animal 側 | 声 |
Cat().speak() |
Cat 側 | にゃー |
| Cat 側を削った後 | Animal 側 | 声 |
子クラスに speak を書いても親の定義そのものは消えません.親のインスタンスでは引き続き親の定義が使われます.上書きは子に対するメソッド選択を変えます.
特殊メソッドと表示
知識
特殊メソッド(special method)は Python の組み込み操作とクラスを結び付ける.__str__ は str(インスタンス) が呼ばれたときに文字列を返し,print の表示にも使われます.必ず文字列を返します.
身近な例として,持ち物に「人に見せるときの名札」を付けるようなものだ.Point(2, 3) という点をそのまま見せると分かりにくいので,(2, 3) と書いた名札を作ります.
special は「特別な」,string は「文字列」です.関連語は repr(開発時の表現)です.発表では “The str method defines the readable display” といえます.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f'({self.x}, {self.y})'
print(Point(2, 3))ヒントを見る
インスタンスごとの属性と、クラスに共通する定義を区別します。別のインスタンスを作った場合に、どの値が独立して変わるかを確認します。
演習の解説を見る
print は点を表示する文字列を必要とします.そこで __str__ が呼ばれ,二つの属性を埋め込んだ文字列を返します.
(2, 3)
def ___(self):
return f'({self.x}, {self.y})'ヒントを見る
インスタンスを文字列として表示するときに使われる特殊メソッドです。座標の文字列表現を返す役割から名前を確認します。
演習の解説を見る
__str__ を入れます.return する値が整数などであれば TypeError になります.
表示までの手順を追う
Point(2, 3) を呼ぶと,__init__ が属性に2と3を保存します.print は表示用の文字列を求めるため __str__ を呼ぶ.return f'({self.x}, {self.y})' が文字列 '(2, 3)' を返し,これが画面に表示されます.
| メソッド | 役割 |
|---|---|
__init__ |
生成時の初期状態を決めます. |
__str__ |
人が読むための表示文字列を返します. |
move など |
呼び出したときに操作を行います. |
__str__ の中で print(...) だけを実行しても文字列は返りません.return を使います.return self.x は数値を返すため不適切です.
図で理解する
練習して確かめる
クラス定義とインスタンス
知識
クラスは同じ形のデータを作る設計図で、インスタンスは具体的な1件。属性に状態を持ち、メソッドに操作をまとめる。
class Student:
def __init__(self, name):
self.name = name
s = Student('A')
print(s.name)Student を2件作り、名前が別々に保存されるか確かめる。
ヒントを見る
別の Student を作ると、別のインスタンスに名前が保存されます。新しいインスタンスを別の変数で受け取ります。
演習の解説
各インスタンスが自分の name 属性を持つ。
空欄を埋め、コードを実行してください。
class Student:
def ___(self, name):
self.name = nameヒントを見る
インスタンスを作ったときに呼ばれ、受け取った name を属性へ保存する初期化メソッドです。
虫食いの解説
class Student:
def __init__(self, name):
self.name = name__init__ を補います。
メソッドと self
知識
メソッドはインスタンスに結びついた関数。self はそのインスタンスを指し、状態を更新するときに使います。
class Counter:
def __init__(self): self.value = 0
def add(self): self.value += 1
c = Counter()
c.add()
print(c.value)add を2回呼び、value の変化を確かめる。
ヒントを見る
add の呼び出し一回ごとに同じ c の属性が更新されます。新しい Counter を作り直す必要はありません。
演習の解説
最初は0で、2回呼べば2になります。
空欄を埋め、コードを実行してください。
def add(self):
___ .value += 1ヒントを見る
ドットの前には、value の持ち主となるインスタンスを表す第1引数名を置きます。属性の値を1だけ増やします。
虫食いの解説
def add(self):
self.value += 1self を補います。
継承と上書き
知識
継承した子クラスは親クラスのメソッドを使えます。同じ名前のメソッドを子側で定義すると上書きされます。共通の振る舞いが本当にあるときに使います。
class Animal:
def speak(self): return '声'
class Cat(Animal):
def speak(self): return 'にゃー'
print(Cat().speak())Cat の speak を消し、親の speak が使われることを確かめる。
ヒントを見る
子クラスの speak をなくすと、親クラスの同名メソッドを受け継ぎます。Cat を作る呼び出しは残します。
演習の解説
上書きを外すと継承した『声』が返る。
空欄を埋め、コードを実行してください。
class Cat(___):
def speak(self): return 'にゃー'ヒントを見る
ここは継承元を指定する場所です。speak がどのクラスのメソッドを置き換えるかを確認します。
虫食いの解説
class Cat(Animal):
def speak(self): return 'にゃー'Animal を補います。
特殊メソッド
知識
__str__ などの特殊メソッドは、組み込み操作を自作クラスに対応させる。print(インスタンス) の表示内容を定義できます。
class Point:
def __init__(self, x, y): self.x, self.y = x, y
def __str__(self): return f'({self.x}, {self.y})'
print(Point(2, 3))Point の x=5、y=8 に変え、表示結果を確かめてください。
ヒントを見る
作成時の二つの引数が、二つの属性へ順に保存されます。文字列表現を作る特殊メソッドは変更しません。
演習の解説
__str__ の返した文字列が表示されます。
空欄を埋め、コードを実行してください。
def ___(self): return f'({self.x}, {self.y})'ヒントを見る
オブジェクトを print したときの文字列表現を定義する特殊メソッドです。二重の下線を含む名前を確認してください。
虫食いの解説
def __str__(self): return f'({self.x}, {self.y})'__str__ を補います。
章末演習(10問)
ここには解答を載せていません。
- 章末演習章末演習 1
書名と価格を持つクラス
Bookを定義し,2冊の情報と価格の合計を表示します。入力
- キーボード入力なし(
input()は使わない)。 - プログラム内で次の2つのインスタンスを作ります。
b1 = Book("Python入門", 2400)b2 = Book("データ分析", 3100)
処理条件
class Book:を定義し,__init__(self, title, price)で受け取った値をインスタンスの属性title(文字列)とprice(整数)に保存します。- リスト
[b1, b2]を for 文で先頭から順に処理し,属性を参照して1冊ずつ表示します。 - 合計は変数
totalを0で始め,同じ for 文の中で+=によって足します。組み込み関数sumとdataclassesモジュールは使いません。
出力
- 1冊につき1行,「書名: 価格円」と表示します。コロンは半角で,その後に半角空白1個を置く。「円」は全角で,数値の直後に空白なしで続ける。
- 最後の行は「合計」,半角空白,合計金額,半角空白,「円」の順に表示します。
- 出力は全3行。実行例と同じ順序・同じ文字(半角・全角,大文字・小文字を含む)で表示します。実行例にない見出し・空行・余分な空白・デバッグ用の表示は出さない(
assertは何も表示しないので自己確認に使ってよい)。
実行例
Python入門: 2400円 データ分析: 3100円 合計 5500 円ヒントを見る
クラスの定義(初期化で何を属性として残すか),インスタンスの作成,属性を読んで表示・合計する部分,の順に組み立てよう。初期化メソッドの引数は,self を通して代入しないとメソッドの終了とともに消えてしまう。
- キーボード入力なし(
- 章末演習章末演習 2
数を数えるクラス
Counterを作り,2つのインスタンスが別々の値を持つことを確かめる。入力
- キーボード入力なし(
input()は使わない)。 - 2つのインスタンス
a = Counter()とb = Counter()をプログラム内で作ります。
処理条件
__init__(self)で属性countを0にします。countはクラス直下に書かず,インスタンスの属性として持つ。increment(self, step=1)はcountをstepだけ増やす。引数を省略したときは1増える。stepには正の整数だけを渡す。reset(self)はcountを0に戻す。どのメソッドも値を返さず,メソッドの中では表示しません。- 次の順に操作する:
a.increment(),a.increment(),a.increment(5),b.increment(),1行目を表示,a.reset(),2行目を表示。
出力
- 各行は「a: aの値 b: bの値」とします。
aとbは半角小文字,コロンは半角で,コロンの後と数値の後に半角空白を1個ずつ置く。 - 1行目はリセット前,2行目は
a.reset()の後の値。 - 出力は全2行。実行例と同じ順序・同じ文字(半角・全角,大文字・小文字を含む)で表示します。実行例にない見出し・空行・余分な空白・デバッグ用の表示は出さない(
assertは何も表示しないので自己確認に使ってよい)。
実行例
a: 7 b: 1 a: 0 b: 1ヒントを見る
引数を省略したときの値は,呼び出す側ではなくメソッドの仮引数の側に書いておきます。a を操作したのに b の値まで変わるなら,値をクラス全体で共有する場所に置いていないか確認しましょう。
- キーボード入力なし(
- 章末演習章末演習 3
幅と高さを持つクラス
Rectangleに,値を返すメソッドと状態を変えるメソッドを作り分ける。入力
- キーボード入力なし(
input()は使わない)。 - プログラム内で
r1 = Rectangle(3, 4)とr2 = Rectangle(5, 5)を作ります。幅・高さ・倍率はすべて正の整数とします。
処理条件
__init__(self, width, height)で属性widthとheightに保存します。area()は面積を,perimeter()は周の長さを整数で返します。is_square()は幅と高さが等しければTrue,そうでなければFalseを返します。scale(self, k)は幅と高さをそれぞれk倍に書き換え,値は返しません。- どのメソッドの中でも
printは使わず,表示はクラスの外で行います。 [r1, r2]を for 文で処理して1・2行目を表示し,その後r1.scale(2)を実行して3行目を表示します。
出力
- 1・2行目は「幅x高さ 面積:値 周:値 正方形:値」とします。
xは半角小文字,コロンは半角でコロンの後に空白を置きません。項目の間は半角空白1個。真偽値はTrue/Falseと表示します。 - 3行目は「拡大後 幅x高さ 面積:値」とします。
- 出力は全3行。実行例と同じ順序・同じ文字(半角・全角,大文字・小文字を含む)で表示します。実行例にない見出し・空行・余分な空白・デバッグ用の表示は出さない(
assertは何も表示しないので自己確認に使ってよい)。
実行例
3x4 面積:12 周:14 正方形:False 5x5 面積:25 周:20 正方形:True 拡大後 6x8 面積:48ヒントを見る
4つのメソッドを「結果を返すもの」と「自分の属性を書き換えるもの」に分けてから書こう。面積を属性として保存してしまうと,拡大した後に古い値が残ることに注意します。
- キーボード入力なし(
- 章末演習章末演習 4
入出金の履歴を残す口座クラス
Accountを作り,残高不足の出金を正しく拒否します。入力
- キーボード入力なし(
input()は使わない)。 - プログラム内で
acc = Account("山田", 1000)を作ります。金額はすべて正の整数とします。
処理条件
__init__(self, owner, balance=0)で属性owner(名義),balance(残高),history(空のリスト)を用意します。historyはインスタンスごとに新しいリストにします。deposit(self, amount)は残高に加え,historyに文字列「入金 金額」を追加します。withdraw(self, amount)は,amountが残高以下なら残高から引いて「出金 金額」を追加しTrueを返す(残高ちょうどの出金は成功し,残高は0になる)。残高より大きければ残高を変えずに「出金失敗 金額」を追加しFalseを返します。- 文字列中の区切りは半角空白1個。メソッドの中では表示しません。
- 操作順:
acc.deposit(500),ok1 = acc.withdraw(2000),ok2 = acc.withdraw(300)。
出力
- 1行目「出金1回目: 戻り値」,2行目「出金2回目: 戻り値」,3行目「残高: 残高」,4行目「履歴:」を表示します。コロンは半角で,値がある行はコロンの後に半角空白1個を置く。
- 5行目以降に
historyの要素を先頭から1行に1つずつ表示します。 - 出力は全7行。実行例と同じ順序・同じ文字(半角・全角,大文字・小文字を含む)で表示します。実行例にない見出し・空行・余分な空白・デバッグ用の表示は出さない(
assertは何も表示しないので自己確認に使ってよい)。
実行例
出金1回目: False 出金2回目: True 残高: 1200 履歴: 入金 500 出金失敗 2000 出金 300ヒントを見る
出金できるかどうかは,残高を減らす前に判定します。失敗の場合を先に処理して戻ってしまうと,成功の場合の処理を深く字下げせずに書けます。境界(残高と同じ額)がどちらに入るかを比較演算子で確かめましょう。
- キーボード入力なし(
- 章末演習章末演習 5
親クラス
Animalと,鳴き声だけを上書きする子クラスDog・Catを作り,同じメソッド呼び出しで異なる結果が出ることを確かめる。入力
- キーボード入力なし(
input()は使わない)。 - プログラム内で
pets = [Dog("ポチ"), Cat("タマ"), Animal("カメ吉")]を作ります。
処理条件
Animalは__init__(self, name)で属性nameを保存し,speak()は文字列"……"(全角の三点リーダー「…」を2個)を返します。Animalのintroduce()は「名前: 鳴き声」の文字列を返します。鳴き声は文字列を直接書かず,speak()を呼び出して得る。DogとCatはAnimalを継承し,speak()だけを定義してそれぞれ"ワン","ニャー"を返します。子クラスには__init__もintroduceも書きません。petsを for 文で処理し,各要素のintroduce()の戻り値を表示します。メソッドの中では表示しません。
出力
- 1匹につき1行,「名前: 鳴き声」と表示します。コロンは半角で,その後に半角空白1個を置く。
- 出力は全3行。実行例と同じ順序・同じ文字(半角・全角,大文字・小文字を含む)で表示します。実行例にない見出し・空行・余分な空白・デバッグ用の表示は出さない(
assertは何も表示しないので自己確認に使ってよい)。
実行例
ポチ: ワン タマ: ニャー カメ吉: ……ヒントを見る
自己紹介の文の組み立ては親クラスに1回だけ書きます。その中で鳴き声を得るときに自分自身のメソッドを呼ぶと,実際のインスタンスが子クラスなら子クラスの定義が使われます。
- キーボード入力なし(
- 章末演習章末演習 6
社員クラス
Employeeを継承して手当付きのManagerを作り,super()で親の処理を再利用して給与を計算します。入力
- キーボード入力なし(
input()は使わない)。 - プログラム内で
staff = [Employee("青木", 250000), Manager("井上", 300000, 50000), Employee("上田", 230000)]を作ります。金額はすべて整数。
処理条件
Employeeは__init__(self, name, base)で属性nameとbaseを保存し,salary()はbaseを返します。Manager(Employee)の__init__(self, name, base, allowance)は,super().__init__(name, base)で名前と基本給を設定してから属性allowanceを保存します。Managerのsalary()はsuper().salary()の結果にallowanceを足して返します。self.baseを直接足す書き方はしません。staffを for 文で処理して各人を表示し,合計は変数totalに+=で足します。組み込み関数sumは使いません。
出力
- 1人につき1行,「名前 給与」と表示する(半角空白1個で区切る。カンマ区切りや「円」は付けない)。
- 最後の行は「合計 合計額」とします。
- 出力は全4行。実行例と同じ順序・同じ文字(半角・全角,大文字・小文字を含む)で表示します。実行例にない見出し・空行・余分な空白・デバッグ用の表示は出さない(
assertは何も表示しないので自己確認に使ってよい)。
実行例
青木 250000 井上 350000 上田 230000 合計 830000ヒントを見る
子クラスでは親と同じ代入を書き直さず,親の初期化を呼んだ後で増えた属性だけを足します。給与の計算も同じ考え方で,親の計算結果に差分を加える。
- キーボード入力なし(
- 章末演習章末演習 7
平面上の点を表すクラス
Pointに特殊メソッドを定義し,+・==・printを自作クラスで使えるようにします。入力
- キーボード入力なし(
input()は使わない)。 - プログラム内で
a = Point(1, 2),b = Point(3, 4)を作ります。座標は整数とします。
処理条件
__init__(self, x, y)で属性x,yを保存します。__str__は「(x, y)」の形の文字列を返す(半角かっこ,半角カンマの後に半角空白1個)。__add__(self, other)は座標どうしを足した新しいPointを返します。selfとotherの属性は書き換えません。__eq__(self, other)はxとyが両方等しいときだけTrueを返します。__ne__は定義しない(Python は__eq__の結果を反転して!=を求める)。- 次の順に表示する:
p = a + bとしてprint(p),print(a),print(p == Point(4, 6)),print(Point(0, 0) != Point(0, 1))。
出力
- 1行目は和の点,2行目は足す前の
a(変化していないことの確認),3・4行目は比較の結果をTrue/Falseで表示します。 - 出力は全4行。実行例と同じ順序・同じ文字(半角・全角,大文字・小文字を含む)で表示します。実行例にない見出し・空行・余分な空白・デバッグ用の表示は出さない(
assertは何も表示しないので自己確認に使ってよい)。
実行例
(4, 6) (1, 2) True Trueヒントを見る
`+` の結果は「新しい点」なので,足し算のメソッドでは自分の属性を書き換えず,計算した座標から新しいインスタンスを作って返します。表示用のメソッドは print するのではなく文字列を返す点にも注意しましょう。
- キーボード入力なし(
- 章末演習章末演習 8
品名と個数を辞書で管理する在庫クラス
Inventoryを作り,len()とprint()に対応させる。入力
- キーボード入力なし(
input()は使わない)。 - プログラム内で
inv = Inventory()を作ります。個数はすべて正の整数とします。
処理条件
__init__で空の辞書を属性itemsに用意する(キー:品名,値:個数)。add(name, qty)は個数を加える。未登録の品名なら新しく登録します。remove(name, qty)は,現在の個数(未登録なら0とみなす)がqty以上なら減らしてTrueを返し,0個になった品名は辞書から削除します。足りなければ何も変えずにFalseを返します。__len__は品目数を返します。__str__は品名をsortedの順(文字コード順)に並べ,「品名:個数」をカンマと半角空白「, 」で区切った文字列を返します。在庫が空なら空文字列を返します。collectionsモジュールは使いません。- 操作順:
add("ペン", 10),add("ノート", 3),add("ペン", 5),r1 = remove("ノート", 3),r2 = remove("ペン", 20),r3 = remove("鉛筆", 1),add("消しゴム", 2)(各メソッドはinv.を付けて呼ぶ)。
出力
- 1〜3行目は
r1〜r3を「ノート3個の削除: 値」「ペン20個の削除: 値」「鉛筆1個の削除: 値」と表示します。 - 4行目は
len(inv)を使って「品目数: 値」,5行目はinvをそのまま埋め込んで「在庫: 文字列」と表示します。コロンは半角で,その後に半角空白1個を置く。 - 出力は全5行。実行例と同じ順序・同じ文字(半角・全角,大文字・小文字を含む)で表示します。実行例にない見出し・空行・余分な空白・デバッグ用の表示は出さない(
assertは何も表示しないので自己確認に使ってよい)。
実行例
ノート3個の削除: True ペン20個の削除: False 鉛筆1個の削除: False 品目数: 2 在庫: ペン:15, 消しゴム:2ヒントを見る
未登録の品名を個別の if で分けなくても,辞書から値を取り出すときに既定値を指定できるメソッドを使えば,加算と在庫確認を同じ形の式で書けます。0個になったときの削除を忘れると品目数が合わなくなります。
- キーボード入力なし(
- 章末演習章末演習 9
図形の親クラス
Shapeに比較と表示の特殊メソッドを置き,子クラスCircle・Rectを面積順に並べる。入力
- キーボード入力なし(
input()は使わない)。 - プログラム内で
shapes = [Rect(3, 4), Circle(1), Rect(2, 2), Circle(2)]を作ります。
処理条件
Shapeには__lt__(self, other)(面積が小さいほうを「小さい」とする)と__str__(「名前 面積 値」の文字列を返す)だけを定義します。Circle(r)は__init__で属性nameを"円",rを半径とし,area()はmath.pi * r ** 2を返します。Rect(w, h)は__init__で属性nameを"長方形",w・hを幅・高さとし,area()はw * hを返します。sorted(shapes)で並べ替える。key=引数は使わず,__lt__による比較で並べること。面積が等しい図形はこのデータにはありません。- 並べた順に図形を表示し,丸める前の面積を変数
totalに+=で足します。
出力
- 図形1個につき1行,「名前 面積 値」と表示します。区切りは半角空白1個。面積は f-string の書式
.2fで小数第2位まで表示する(整数の面積も「4.00」のように表示する)。 - 最後の行は「合計 値」とし,値は同じく
.2fで表示します。 - 出力は全5行。実行例と同じ順序・同じ文字(半角・全角,大文字・小文字を含む)で表示します。実行例にない見出し・空行・余分な空白・デバッグ用の表示は出さない(
assertは何も表示しないので自己確認に使ってよい)。
実行例
円 面積 3.14 長方形 面積 4.00 長方形 面積 12.00 円 面積 12.57 合計 31.71ヒントを見る
並べ替えは要素どうしを「小なり」で比べて行われます。比較と表示を親クラスに書き,その中で各図形自身の面積メソッドを呼べば,子クラスには面積の求め方だけを書けばよいでしょう。合計は表示用に丸めた値ではなく元の面積で足そう。
- キーボード入力なし(
- 章末演習章末演習 10
生徒クラス
Studentと,生徒をまとめて管理するClassroomを作り,平均点の順位表を表示します。入力
- キーボード入力なし(
input()は使わない)。 - プログラム内で
room = Classroom()を作り,次の3人をroom.add(...)で順に加える。 Student("伊藤", [80, 90, 70])Student("加藤", [95, 85, 90])Student("小林", [60, 75, 72])
処理条件
Student(name, scores)は属性nameとscores(1個以上の整数のリスト)を持ち,average()は平均点を返す(sumとlenを使ってよい)。Classroomは__init__で空のリストを用意し,add(student)で生徒を加え,__len__で人数を返します。ranking()は(平均点, 名前)のタプルのリストを平均点の高い順に並べて返します。このデータに同じ平均点の生徒はいません。- 順位の番号は第12章の
enumerate(start=1)で付ける。番号を自分で数える変数は使いません。
出力
- 1行目は
len(room)を使って「人数: 値」と表示する(コロンは半角,後ろに半角空白1個)。 - 2行目以降は順位の高い順に「順位位 名前 平均点」と表示します。区切りは半角空白1個,平均点は
.1fで小数第1位まで表示します。 - 出力は全4行。実行例と同じ順序・同じ文字(半角・全角,大文字・小文字を含む)で表示します。実行例にない見出し・空行・余分な空白・デバッグ用の表示は出さない(
assertは何も表示しないので自己確認に使ってよい)。
実行例
人数: 3 1位 加藤 90.0 2位 伊藤 80.0 3位 小林 69.0ヒントを見る
タプルどうしの比較は先頭の要素から行われます。どの値を先頭に置けば並べ替えがそのまま順位順になるかを考えよう。enumerate が返す組をそのまま分解すれば,順位と中身を同時に受け取れます。
- キーボード入力なし(