動画
課題
課題(チャプター7:オブジェクト指向の基本)
【基本問題】クラスとインスタンス(8問)
問題1
空のクラスProductを定義し、appleとbananaの2つのインスタンスを作成してください。その後、print(type(apple))を実行して型を表示してください。
期待される出力:
<class '__main__.Product'>
ヒント: クラス定義はclass Product:の形です。インスタンス生成はapple = Product()のように書きます。
問題2
問題1の続きとして、appleとbananaを作成したあと、print(apple is banana)を実行して、2つが別のインスタンスであることを確認してください。
期待される出力:
False
ヒント: isは「同一オブジェクトかどうか」を判定します。
問題3
クラス名は先頭大文字(アッパーキャメルケース)で書くのが慣例です。クラスStudentを定義し、student1というインスタンスを作成してから、print(type(student1))を表示してください。
期待される出力:
<class '__main__.Student'>
ヒント: インスタンス名は小文字(スネークケース)で書くことが多いです。
問題4
空のクラスBoxを定義し、bというインスタンスを作成してください。その後、print(isinstance(b, Box))を実行して、bがBoxのインスタンスであることを確認してください。
期待される出力:
True
ヒント: isinstance(オブジェクト, クラス)です。
問題5
クラスCounterを定義し、インスタンスcを作ってください。そのあと、print(type(1))とprint(type("A"))とprint(type([]))を順に表示し、「数値・文字列・リストもクラスの一種」であることを確認してください。
期待される出力:
<class 'int'>
<class 'str'>
<class 'list'>
ヒント: ここではcは使わなくても構いません。確認用にtypeを表示します。
問題6
クラスProductを定義し、appleインスタンスを1つ作成してください。その後、print(hasattr(apple, "name"))を表示して、まだ属性が設定されていないことを確認してください。
期待される出力:
False
ヒント: クラスを書いただけではデータは入りません。属性は後で付けるか、__init__で初期化します。
問題7
クラスProductを定義し、インスタンスを2つ作成してください。片方にだけname属性を設定し、もう片方には設定しない状態で、print(hasattr(...))を2回表示して違いを確認してください(属性を設定した方がTrue、設定していない方がFalseになるように)。
期待される出力:
True
False
ヒント: obj.name = "りんご"のようにドット記法で属性を追加できます。
問題8
クラスProductを定義し、インスタンスappleを作成してapple.price = 120を設定してください。その後、print(apple.price)を表示してください。
期待される出力:
120
ヒント: ドット記法は「読む」「更新する」の両方に使えます。
【基本問題】ドット記法とインスタンス属性(10問)
問題9
クラスProductを定義し、appleを作成してください。apple.nameに"りんご"、apple.priceに120、apple.stockに10を設定し、3つをこの順に1行ずつ表示してください。
期待される出力:
りんご
120
10
ヒント: 台本のapple.name = ...の例と同じです。
問題10
クラスProductを定義し、appleを作成してapple.price = 120としてください。その後、apple.priceを150に更新してからprint(apple.price)を表示してください。
期待される出力:
150
ヒント: 同じ属性名に再代入すれば更新になります。
問題11
apple.stock = 10と設定したあと、apple.stock -= 3で在庫を減らし、print(apple.stock)を表示するプログラムを作成してください。
期待される出力:
7
ヒント: -=は「引いて代入」です。属性も同様に更新できます。
問題12
クラスStudentを定義し、s1とs2の2つのインスタンスを作成してください。s1.name = "田中"、s2.name = "佐藤"とし、2人の名前をこの順に1行ずつ表示してください。
期待される出力:
田中
佐藤
ヒント: 同じクラスから作っても、インスタンス属性は別々に持てます。
問題13
クラスProductを定義し、appleとbananaを作成してください。両方にprice属性を設定し、apple.priceは120、banana.priceは80にしてください。最後にprint(apple.price + banana.price)を表示してください。
期待される出力:
200
ヒント: 属性も通常の数値として計算できます。
問題14
クラスCartを定義し、インスタンスcartを作成してください。cart.items = []とした後、文字列"りんご"をcart.itemsに追加し、print(cart.items)を表示してください。
期待される出力:
['りんご']
ヒント: cart.items.append("りんご")のように、属性がリストならリストのメソッドが使えます。
問題15
次の説明を満たすようにプログラムを作成してください。cart.itemsを空のリストにし、"A"と"B"の2つを順に追加して、最後にprint(cart.items)を表示します。
期待される出力:
['A', 'B']
ヒント: ドット記法は「属性アクセス」と「メソッド呼び出し」の両方で使われます(obj.nameとobj.method())。
問題16
クラスProductを定義し、appleを作成してapple.nameに"りんご"を設定してください。その後、print("商品:", apple.name)を表示するプログラムを作成してください。
期待される出力:
商品: りんご
ヒント: 属性は普通の変数と同じようにprintに渡せます。
問題17
クラスProductを定義し、appleを作成してapple.price = 120、apple.stock = 10を設定してください。最後にprint(apple.price * apple.stock)を表示し、売り切るといくらになるか計算してください。
期待される出力:
1200
ヒント: 「データ(属性)」はオブジェクトの状態です。計算はその状態を使って行えます。
問題18
obj.methodとobj.method()の違いを確認するため、クラスAを定義し、メソッドhelloでprint("hi")を実行するようにしてください。インスタンスaを作った後、a.hello()を呼び出して表示してください(a.helloだけは書かない)。
期待される出力:
hi
ヒント: ()が付いて初めて「呼び出し」になります。
【基本問題】メソッドとself(10問)
問題19
クラスProductを定義し、メソッドreduce_stockを作成してください。reduce_stockは引数にqtyを受け取り、self.stockからqtyを引くようにします。apple.stock = 10からapple.reduce_stock(2)を実行し、最後にprint(apple.stock)を表示してください。
期待される出力:
8
ヒント: 定義側はdef reduce_stock(self, qty):です。呼び出し側はapple.reduce_stock(2)と書きます(selfは渡しません)。
問題20
クラスGreeterを定義し、メソッドsayでprint("Hello")を実行するようにしてください。インスタンスgを作り、g.say()を1回呼び出してください。
期待される出力:
Hello
ヒント: メソッド定義の第1引数にselfが必要です。
問題21
クラスProductを定義し、メソッドsubtotalを作成してください。subtotalは引数でqtyを受け取り、self.price * qtyをreturnするようにします。apple.price = 120としてから、print(apple.subtotal(3))を表示してください。
期待される出力:
360
ヒント: メソッドもチャプター6の関数と同じく、戻り値を返せます。
問題22
クラスStudentを定義し、属性nameを後から設定できるようにします。メソッドshowを作成し、print(self.name)を実行するようにしてください。s.name = "田中"のあとs.show()を呼んで表示してください。
期待される出力:
田中
ヒント: メソッド内で属性にアクセスするときはself.nameです。
問題23
クラスBankAccountを定義し、属性balanceを後から設定できるようにします。メソッドdepositを作り、引数amountを受け取ってself.balance += amountするようにしてください。acc.balance = 100からacc.deposit(50)を実行し、最後にprint(acc.balance)を表示してください。
期待される出力:
150
ヒント: 「どの口座の残高を増やすか」を示すのがselfです。
問題24
クラスProductにメソッドlabelを作り、print(self.name, self.price)を実行するようにしてください。apple.name = "りんご"、apple.price = 120のあと、apple.label()を呼び出してください。
期待される出力:
りんご 120
ヒント: printに複数の値を渡すとスペース区切りで表示されます。
問題25
クラスCartを定義し、メソッドadd_itemでself.itemsに(product, qty)のタプルを追加するようにしてください(self.itemsは事前に空リストとして用意)。cartに"りんご"を数量2で追加し、print(cart.items)を表示してください。
期待される出力:
[('りんご', 2)]
ヒント: タプルは(値1, 値2)です。リストへの追加はappendです。
問題26
クラスCartを定義し、__init__ではなく後からcart.items = []を設定してもよい形にします。メソッドcount_itemsを作り、return len(self.items)を返すようにしてください。cart.itemsに3つ要素を追加してから、print(cart.count_items())を表示してください。
期待される出力:
3
ヒント: lenは「要素数」を返す関数です。
問題27
次のコードの空欄を埋めて、期待される出力になるようにしてください(selfを正しく使います)。
class A:
def set_x(self, x):
???
obj = A()
obj.set_x(5)
print(obj.x)
期待される出力:
5
ヒント: インスタンスに値を保存するときはself.x = xの形です。
問題28
次の説明を満たすようにプログラムを作成してください。クラスTimerを定義し、属性secを後から設定できるようにします。メソッドtickを作り、self.sec += 1で1秒進めるようにしてください。t.sec = 0からtickを2回呼び、最後にprint(t.sec)を表示してください。
期待される出力:
2
ヒント: 「どのタイマーの値か」を指定するためにselfが必要です。
【基本問題】__init__で初期化(10問)
問題29
クラスProductを定義し、__init__でname、price、stockを受け取り、self.name、self.price、self.stockに代入してください。apple = Product("りんご", 120, 10)を作り、print(apple.name, apple.price, apple.stock)を表示してください。
期待される出力:
りんご 120 10
ヒント: __init__はインスタンス生成時に自動で呼ばれます。
問題30
問題29のProductクラスを使い、appleとbananaの2つのインスタンスを作成してください(bananaは"バナナ"、80、5)。それぞれのnameとstockだけをこの順に表示してください。
期待される出力:
りんご 10
バナナ 5
ヒント: print(obj.name, obj.stock)の形です。
問題31
クラスStudentを定義し、__init__でnameとscoreを受け取り、インスタンス属性に保存してください。Student("田中", 80)を作り、print(s.name, s.score)を表示してください。
期待される出力:
田中 80
ヒント: 初期化で必須項目を入れると「未設定」を防げます。
問題32
クラスProductに、問題29の__init__に加えてメソッドreduce_stock(qtyを引く)を作成してください。apple = Product("りんご", 120, 10)を作ってapple.reduce_stock(3)を実行し、最後にprint(apple.stock)を表示してください。
期待される出力:
7
ヒント: 「属性(状態)」と「操作(メソッド)」がセットになります。
問題33
クラスProductにメソッドsubtotalを作り、qtyを受け取って小計(self.price * qty)を返すようにしてください。apple = Product("りんご", 120, 10)を作り、print("小計:", apple.subtotal(3))を表示してください。
期待される出力:
小計: 360
ヒント: 戻り値はprintの中に直接書けます。
問題34
クラスCartを定義し、__init__でself.items = []を初期化してください。cart = Cart()を作り、print(cart.items)を表示してください。
期待される出力:
[]
ヒント: 空リストの表示は[]です(HTML内では[]のように見えます)。
問題35
問題34のCartにメソッドadd_itemを作り、(product, qty)をself.itemsに追加するようにしてください。cart.add_item("りんご", 2)を呼び、print(cart.items)を表示してください。
期待される出力:
[('りんご', 2)]
ヒント: 台本のCartの例と同じです(中身は文字列で代用してOK)。
問題36
クラスCartにメソッドtotal_priceを作り、self.itemsに入っている(price, qty)を使って合計金額を計算して返すようにしてください(ここではproductの代わりに単純な価格の数値を入れてよい)。cart.add_item(120, 2)とcart.add_item(80, 3)を行い、print(cart.total_price())を表示してください。
期待される出力:
480
ヒント: for price, qty in self.items:で取り出せます。合計はtotal += price * qtyです。
問題37
次のコードの__init__には間違いがあります。インスタンス生成時にエラーが出ないように修正してください(正しくは第1引数にselfが必要です)。
class A:
def __init__():
pass
a = A()
print("ok")
期待される出力:
ok
ヒント: インスタンスメソッド(__init__含む)の定義は、先頭にselfが必要です。
問題38
次のコードは属性名の揺れが原因でエラーになります。self.Nameではなく、統一してself.nameを使うように修正し、print(s.name)が田中と表示されるようにしてください。
class Student:
def __init__(self, name):
self.Name = name
s = Student("田中")
print(s.name)
期待される出力:
田中
ヒント: 属性名の大文字小文字違いは別物として扱われます。命名を統一しましょう。
【基本問題】クラス属性(共有データ)と違い(7問)
問題39
クラスProductを定義し、クラス属性tax_rate = 0.10を設定してください。メソッドprice_with_taxを作り、return int(self.price * (1 + Product.tax_rate))を返すようにしてください。apple = Product("りんご", 120, 10)を作り、print(apple.price_with_tax())を表示してください。
期待される出力:
132
ヒント: 税率のような「全体共通の設定」はクラス属性にすると便利です。
問題40
問題39のProductクラスを使い、apple = Product("りんご", 120, 10)とbanana = Product("バナナ", 80, 5)を作成してください。2つの税込価格を、この順に表示してください。
期待される出力:
132
88
ヒント: 税率は共通でも、priceは各インスタンス属性なので結果が変わります。
問題41
問題39のProductについて、print(Product.tax_rate)を実行して税率を表示するプログラムを作成してください。
期待される出力:
0.1
ヒント: クラス属性はクラス名.属性で参照できます。
問題42
問題39のProductについて、クラス属性tax_rateを0.08に変更し、apple = Product("りんご", 120, 10)の税込価格を表示してください(税率変更後にインスタンス生成してOK)。
期待される出力:
129
ヒント: 税率の変更はProduct.tax_rate = 0.08のように行います。
問題43
インスタンス属性とクラス属性の違いを確認します。クラスAにクラス属性x = 1を定義し、インスタンスaを作成してください。その後、a.x = 5としてからprint(a.x)とprint(A.x)をこの順に表示してください。
期待される出力:
5
1
ヒント: インスタンスに代入すると、同名のインスタンス属性が作られてクラス属性とは別扱いになることがあります。
問題44
クラス属性に可変オブジェクトを置く注意点を確認します。クラスBにクラス属性items = []を定義し、b1とb2の2つのインスタンスを作成してください。b1.items.append("A")を実行したあと、print(b2.items)を表示してください。
期待される出力:
['A']
ヒント: クラス属性のリストは「全インスタンスで共有」されるため、意図しない共有が起きます。
問題45
問題44の「共有が起きる」問題を避けるため、クラスCを定義し、__init__でself.items = []を初期化するようにしてください。c1とc2を作成し、c1.items.append("A")のあとにprint(c2.items)を表示してください(共有されないことを確認します)。
期待される出力:
[]
ヒント: 可変のリストは、クラス属性ではなくインスタンス属性として持たせるのが基本です。
【間違い探し】self/呼び出し/設計の混乱ポイント(5問)
問題46
次のコードは、メソッド定義にselfがなく、呼び出しでエラーになります。正しく修正してOKと表示されるようにしてください。
class A:
def hello():
print("OK")
a = A()
a.hello()
期待される出力:
OK
ヒント: インスタンスメソッドはdef hello(self):の形です。
問題47
次のコードは、メソッドを呼び出していないため何も表示されません。()を付けて正しく呼び出し、Hiが表示されるようにしてください。
class A:
def hi(self):
print("Hi")
a = A()
a.hi
期待される出力:
Hi
ヒント: obj.methodは「メソッドそのもの」で、obj.method()が「呼び出し」です。
問題48
次のコードは、属性stockを設定する前に減らそうとしてエラーになります。__init__でstockを初期化するか、生成後に設定するなどして、最終的に8が表示されるように修正してください(どちらの方法でもOK)。
class Product:
def reduce_stock(self, qty):
self.stock -= qty
apple = Product()
apple.reduce_stock(2)
print(apple.stock)
期待される出力:
8
ヒント: 生成直後に必要な値を必ず入れるなら__init__が適しています。
問題49
次のコードは、total_priceが属性アクセスになっており、メソッド呼び出しではありません。正しくメソッドを呼び出して合計200が表示されるように修正してください。
class Cart:
def __init__(self):
self.items = []
def add_item(self, price, qty):
self.items.append((price, qty))
def total_price(self):
total = 0
for price, qty in self.items:
total += price * qty
return total
cart = Cart()
cart.add_item(100, 1)
cart.add_item(50, 2)
print(cart.total_price)
期待される出力:
200
ヒント: ()を付けると呼び出しになります。
問題50
設計の練習です。次の条件を満たすように、ProductとCartの2クラスで小さなモデルを作ってください。
条件:Productはnameとpriceを持ち、Cartはitems((product, qty)のリスト)を持つ。Cartのtotal_priceは合計金額を返す。apple = Product("りんご", 120)とbanana = Product("バナナ", 80)を作り、cartに(apple, 2)と(banana, 3)を追加して、最後にprint(cart.total_price())で合計を表示してください。
期待される出力:
480
ヒント: 台本の「商品(データ+処理)」と「カート(複数商品をまとめる)」の分離の考え方です。total_priceではproduct.priceを使います。
