Python プログラム練習問題 10 問:クラスを活用する
Python の学習において、オブジェクト指向プログラミング (OOP) は非常に重要な概念です。OOP の中心となるのが「クラス」であり、データとそれを操作するメソッドをまとめることで、コードの再利用性、保守性、拡張性を高めます。
本記事では、Python のクラスを活用した練習問題を 10 問取り上げます。初心者の方でも理解しやすいように、各問題に対して丁寧な解説とサンプルコードを提供します。また、必要に応じて関連する Python ドキュメントや参考資料へのリンクも記載します。
クラスとは?
まず、クラスとは何かを簡単に説明します。クラスは、オブジェクトの設計図のようなものです。例えば、「犬」というクラスを定義すると、そのクラスから「ポチ」「タロウ」といった具体的な犬のオブジェクトを作成できます。各オブジェクトは、犬としての共通の特徴(名前、毛色、年齢など)を持ちながらも、それぞれ異なる個性を持ちます。
Python におけるクラスの基本的な構文は以下の通りです。
class クラス名: def __init__(self, 引数1, 引数2, ...): # コンストラクタ self.属性1 = 引数1 self.属性2 = 引数2 ... def メソッド名(self, 引数1, 引数2, ...): # メソッドの処理 return 戻り値
class
: クラスを定義するためのキーワード。クラス名
: クラスの名前(例:Dog
,Car
,Rectangle
)。__init__(self, 引数1, 引数2, ...)
: コンストラクタと呼ばれる特別なメソッドで、オブジェクトが作成される際に自動的に呼び出されます。self
は、そのオブジェクト自身を指します。コンストラクタでは、オブジェクトの属性(データ)を初期化します。self.属性1 = 引数1
: オブジェクトの属性を定義し、初期値を設定します。メソッド名(self, 引数1, 引数2, ...)
: クラスに属する関数です。オブジェクトの状態を変更したり、特定の処理を実行するために使用されます。
What is a Class? (English Explanation)
A class in Python acts as a blueprint or template for creating objects. Think of it like a cookie cutter – the cutter defines the shape and characteristics of the cookies, but each individual cookie is an object created from that cutter. In programming terms, a class defines what data (attributes) an object will hold and what actions (methods) it can perform. For example, you could define a "Dog" class with attributes like name, breed, and age, and methods like bark() or fetch(). Then, you can create multiple Dog objects, each with its own unique values for those attributes.
練習問題と解説
それでは、クラスを活用した練習問題に取り組みましょう。
問題 1:シンプルな Dog クラスを作成する
犬の名前と種類を属性として持ち、紹介文を表示するメソッドを持つ Dog
クラスを作成してください。
class Dog: def __init__(self, name, breed): self.name = name self.breed = breed def introduce(self): print(f"こんにちは!私の名前は{self.name}、犬種は{self.breed}です。") # Dog オブジェクトの作成とメソッド呼び出し my_dog = Dog("ポチ", "柴犬") my_dog.introduce() # 出力: こんにちは!私の名前はポチ、犬種は柴犬です。
解説:
__init__(self, name, breed)
: コンストラクタで、name
とbreed
を引数として受け取り、それぞれオブジェクトの属性self.name
とself.breed
に代入しています。introduce(self)
: 紹介文を表示するメソッドです。f-string
を使用して、オブジェクトの属性を文字列に埋め込んでいます。
Problem 1: Create a Simple Dog Class (English Explanation)
This problem asks you to create a Dog
class that has two attributes: name
and breed
. It also requires a method called introduce
which prints a greeting message including the dog's name and breed.
The code defines a class named Dog
. The __init__
method initializes the name
and breed
attributes of each Dog object. The introduce
method uses an f-string to format and print a personalized introduction for the dog. Finally, it creates a Dog
object called my_dog
with the name "ポチ" (Pochi) and breed "柴犬" (Shiba Inu), then calls the introduce
method to display its greeting.
問題 2:Rectangle クラスを作成し、面積を計算する
幅と高さを属性として持ち、面積を計算するメソッドを持つ Rectangle
クラスを作成してください。
class Rectangle: def __init__(self, width, height): self.width = width self.height = height def calculate_area(self): return self.width * self.height # Rectangle オブジェクトの作成とメソッド呼び出し my_rectangle = Rectangle(5, 10) area = my_rectangle.calculate_area() print(f"面積: {area}") # 出力: 面積: 50
解説:
__init__(self, width, height)
: コンストラクタで、width
とheight
を引数として受け取り、それぞれオブジェクトの属性self.width
とself.height
に代入しています。calculate_area(self)
: 面積を計算するメソッドです。幅と高さの積を返します。
Problem 2: Create a Rectangle Class and Calculate Area (English Explanation)
This problem asks you to create a Rectangle
class with attributes for width and height. It also requires a method called calculate_area
that computes and returns the area of the rectangle.
The code defines a class named Rectangle
. The __init__
method initializes the width
and height
attributes. The calculate_area
method multiplies the width and height to calculate the area, which is then returned. An instance of the Rectangle
class (my_rectangle
) is created with dimensions 5x10, and its area is calculated using the calculate_area
method. The result is printed to the console.
問題 3:BankAccount クラスを作成する (残高管理)
口座番号、所有者名、初期残高を属性として持ち、預金、引き出し、残高照会を行うメソッドを持つ BankAccount
クラスを作成してください。
class BankAccount: def __init__(self, account_number, owner_name, initial_balance): self.account_number = account_number self.owner_name = owner_name self.balance = initial_balance def deposit(self, amount): self.balance += amount print(f"{amount}円を預金しました。現在の残高: {self.balance}円") def withdraw(self, amount): if self.balance >= amount: self.balance -= amount print(f"{amount}円を引き出しました。現在の残高: {self.balance}円") else: print("残高不足です。") def check_balance(self): print(f"現在の残高: {self.balance}円") # BankAccount オブジェクトの作成とメソッド呼び出し my_account = BankAccount("1234567890", "山田太郎", 10000) my_account.deposit(5000) my_account.withdraw(3000) my_account.check_balance()
解説:
__init__(self, account_number, owner_name, initial_balance)
: コンストラクタで、口座番号、所有者名、初期残高を引数として受け取り、それぞれオブジェクトの属性self.account_number
,self.owner_name
,self.balance
に代入しています。deposit(self, amount)
: 預金処理を行うメソッドです。残高に金額を加算し、メッセージを表示します。withdraw(self, amount)
: 引き出し処理を行うメソッドです。残高が金額以上であれば、残高から金額を減算し、メッセージを表示します。そうでなければ、「残高不足です。」と表示します。check_balance(self)
: 残高照会処理を行うメソッドです。現在の残高を表示します。
Problem 3: Create a BankAccount Class (Balance Management) (English Explanation)
This problem requires you to create a BankAccount
class with attributes for account number, owner name, and initial balance. It also needs methods for depositing funds, withdrawing funds, and checking the balance.
The code defines a class named BankAccount
. The __init__
method initializes the account number, owner name, and balance attributes. The deposit
method adds an amount to the balance and prints a confirmation message. The withdraw
method checks if there are sufficient funds before subtracting the withdrawal amount from the balance; otherwise, it displays an "Insufficient Funds" message. Finally, the check_balance
method simply prints the current balance. An instance of the BankAccount
class (my_account
) is created with specific details and then used to perform deposit, withdrawal, and balance check operations.
問題 4:Employee クラスを作成する (給与計算)
社員番号、氏名、基本給を属性として持ち、残業時間に応じて給与を計算するメソッドを持つ Employee
クラスを作成してください。残業時間は1時間あたり1500円とします。
class Employee: def __init__(self, employee_id, name, base_salary): self.employee_id = employee_id self.name = name self.base_salary = base_salary def calculate_salary(self, overtime_hours): overtime_pay = overtime_hours * 1500 total_salary = self.base_salary + overtime_pay return total_salary # Employee オブジェクトの作成とメソッド呼び出し employee1 = Employee("E001", "佐藤花子", 250000) salary = employee1.calculate_salary(10) print(f"{employee1.name}さんの給与: {salary}円") # 出力: 佐藤花子さんの給与: 315000円
解説:
__init__(self, employee_id, name, base_salary)
: コンストラクタで、社員番号、氏名、基本給を引数として受け取り、それぞれオブジェクトの属性self.employee_id
,self.name
,self.base_salary
に代入しています。calculate_salary(self, overtime_hours)
: 残業時間に応じて給与を計算するメソッドです。残業代を計算し、基本給に加算して合計給与を返します。
Problem 4: Create an Employee Class (Salary Calculation) (English Explanation)
This problem asks you to create an Employee
class with attributes for employee ID, name, and base salary. It also requires a method called calculate_salary
that calculates the total salary based on overtime hours (with an hourly rate of 1500 yen).
The code defines a class named Employee
. The __init__
method initializes the employee ID, name, and base salary attributes. The calculate_salary
method calculates overtime pay by multiplying the number of overtime hours by 1500, then adds it to the base salary to determine the total salary, which is returned. An instance of the Employee
class (employee1
) is created with specific details, and its salary is calculated using the calculate_salary
method for a given number of overtime hours. The result is printed to the console.
問題 5:Circle クラスを作成する (面積と円周の計算)
半径を属性として持ち、面積と円周を計算するメソッドを持つ Circle
クラスを作成してください。円周率 π は math.pi
を使用してください。
import math class Circle: def __init__(self, radius): self.radius = radius def calculate_area(self): return math.pi * self.radius ** 2 def calculate_circumference(self): return 2 * math.pi * self.radius # Circle オブジェクトの作成とメソッド呼び出し my_circle = Circle(5) area = my_circle.calculate_area() circumference = my_circle.calculate_circumference() print(f"面積: {area}, 円周: {circumference}")
解説:
__init__(self, radius)
: コンストラクタで、半径を引数として受け取り、オブジェクトの属性self.radius
に代入しています。calculate_area(self)
: 面積を計算するメソッドです。円周率 π をmath.pi
から取得し、半径の2乗に掛けて面積を計算します。calculate_circumference(self)
: 円周を計算するメソッドです。円周率 π と半径を用いて円周を計算します。
Problem 5: Create a Circle Class (Area and Circumference Calculation) (English Explanation)
This problem requires you to create a Circle
class with a radius attribute, and methods for calculating the area and circumference of the circle. Use math.pi
for the value of pi.
The code defines a class named Circle
. The __init__
method initializes the radius attribute. The calculate_area
method calculates the area using the formula π * r2, where r is the radius. The calculate_circumference
method calculates the circumference using the formula 2 * π * r. An instance of the Circle
class (my_circle
) is created with a specific radius, and its area and circumference are calculated and printed to the console.
問題 6:クラスの継承を利用する (Animal と Dog)
Animal
クラスを定義し、名前と鳴き声を属性として持ちます。次に、Dog
クラスを Animal
クラスを継承して作成し、犬種を追加します。Dog
クラスには、紹介文を表示するメソッドを作成してください。
class Animal: def __init__(self, name, sound): self.name = name self.sound = sound def make_sound(self): print(f"{self.name} は {self.sound} と鳴きます。") class Dog(Animal): def __init__(self, name, breed, sound="わん"): # Animalの引数に加えて犬種を追加 super().__init__(name, sound) # 親クラスのコンストラクタを呼び出す self.breed = breed def introduce(self): print(f"こんにちは!私の名前は{self.name}、犬種は{self.breed}です。鳴き声は {self.sound} です。") # Dog オブジェクトの作成とメソッド呼び出し my_dog = Dog("ポチ", "柴犬") my_dog.introduce() # 出力: こんにちは!私の名前はポチ、犬種は柴犬です。鳴き声は わん です。 my_dog.make_sound() # 出力: ポチ は わん と鳴きます。
解説:
Animal
クラス: 名前と鳴き声を属性として持ち、鳴き声を出すメソッドmake_sound()
を持ちます。Dog(Animal)
:Animal
クラスを継承したクラスです。犬種を追加し、紹介文を表示するメソッドintroduce()
を持ちます。super().__init__(name, sound)
: 親クラス (Animal
) のコンストラクタを呼び出して、名前と鳴き声を初期化します。
Problem 6: Using Class Inheritance (Animal and Dog) (English Explanation)
This problem requires you to define an Animal
class with attributes for name and sound. Then, create a Dog
class that inherits from the Animal
class and adds a breed attribute. The Dog
class should also have a method to display an introduction message.
The code defines an Animal
class with attributes for name and sound, and a method called make_sound
. A Dog
class is then created by inheriting from the Animal
class. It adds a breed attribute and includes an introduce
method that displays an introductory message including the dog's name, breed, and sound. The super().__init__(name, sound)
call within the Dog
constructor ensures that the parent class's initialization logic is executed correctly. An instance of the Dog
class (my_dog
) is created with specific details and used to demonstrate both the inherited make_sound
method and the custom introduce
method.
問題 7:クラスの継承を利用する (Vehicle と Car)
Vehicle
クラスを定義し、メーカーとモデルを属性として持ちます。次に、Car
クラスを Vehicle
クラスを継承して作成し、ドア数を追加します。Car
クラスには、詳細情報を表示するメソッドを作成してください。
class Vehicle: def __init__(self, manufacturer, model): self.manufacturer = manufacturer self.model = model def display_info(self): print(f"メーカー: {self.manufacturer}, モデル: {self.model}") class Car(Vehicle): def __init__(self, manufacturer, model, num_doors): super().__init__(manufacturer, model) self.num_doors = num_doors def display_details(self): super().display_info() # 親クラスのメソッドを呼び出す print(f"ドア数: {self.num_doors}") # Car オブジェクトの作成とメソッド呼び出し my_car = Car("トヨタ", "カローラ", 4) my_car.display_details() # 出力: メーカー: トヨタ, モデル: カローラ、ドア数: 4
解説:
Vehicle
クラス: メーカーとモデルを属性として持ち、基本的な情報を表示するメソッドdisplay_info()
を持ちます。Car(Vehicle)
:Vehicle
クラスを継承したクラスです。ドア数を追加し、詳細情報を表示するメソッドdisplay_details()
を持ちます。super().display_info()
: 親クラス (Vehicle
) のメソッドdisplay_info()
を呼び出して、メーカーとモデルを表示します。
Problem 7: Using Class Inheritance (Vehicle and Car) (English Explanation)
This problem requires you to define a Vehicle
class with attributes for manufacturer and model. Then, create a Car
class that inherits from the Vehicle
class and adds a number of doors attribute. The Car
class should have a method to display detailed information.
The code defines a Vehicle
class with attributes for manufacturer and model, and a method called display_info
. A Car
class is then created by inheriting from the Vehicle
class. It adds a num_doors attribute and includes a display_details
method that calls the parent's display_info
method using super().display_info()
to display the manufacturer and model, followed by the number of doors. An instance of the Car
class (my_car
) is created with specific details and used to demonstrate the inherited and custom methods.
問題 8:クラスの継承とオーバーライド (Shape と Circle)
Shape
クラスを定義し、面積を計算する抽象メソッド calculate_area()
を持ちます。次に、Circle
クラスを Shape
クラスを継承して作成し、半径を属性として持ち、calculate_area()
メソッドをオーバーライドして、円の面積を計算するようにします。
import math class Shape: def calculate_area(self): raise NotImplementedError("サブクラスで実装してください") # 抽象メソッド class Circle(Shape): def __init__(self, radius): self.radius = radius def calculate_area(self): return math.pi * self.radius ** 2 # Circle オブジェクトの作成とメソッド呼び出し my_circle = Circle(5) area = my_circle.calculate_area() print(f"面積: {area}") # 出力: 面積: 78.53981633974483
解説:
Shape
クラス:calculate_area()
メソッドを定義していますが、これは抽象メソッドです。サブクラスで必ずオーバーライドする必要があります。Circle(Shape)
:Shape
クラスを継承したクラスです。半径を属性として持ち、calculate_area()
メソッドをオーバーライドして、円の面積を計算します。raise NotImplementedError("サブクラスで実装してください")
: 抽象メソッドは、基底クラスで具体的な実装を持たず、派生クラスに実装を強制するために使用されます。
Problem 8: Class Inheritance and Overriding (Shape and Circle) (English Explanation)
This problem requires you to define a Shape
class with an abstract method called calculate_area
. Then, create a Circle
class that inherits from the Shape
class, adds a radius attribute, and overrides the calculate_area
method to calculate the area of a circle.
The code defines a Shape
class with a calculate_area
method that raises a NotImplementedError
, making it an abstract method. A Circle
class is then created by inheriting from the Shape
class. It adds a radius attribute and overrides the calculate_area
method to calculate the area of a circle using the formula π * r2. The use of raise NotImplementedError
in the base class enforces that subclasses must provide their own implementation of this method. An instance of the Circle
class (my_circle
) is created with a specific radius, and its area is calculated and printed to the console.
問題 9:クラスのメソッドと静的メソッド (MathHelper)
数学的な計算を行うための MathHelper
クラスを作成します。このクラスには、2つの数の合計を計算するインスタンスメソッド add()
と、クラス変数を使用して2つの数の積を計算する静的メソッド multiply()
を含めます。
class MathHelper: # クラス変数 multiplier = 2 def __init__(self, x, y): self.x = x self.y = y def add(self): return self.x + self.y @staticmethod def multiply(x, y): return x * y * MathHelper.multiplier # クラス変数を使用 # MathHelper オブジェクトの作成とメソッド呼び出し helper = MathHelper(5, 3) sum_result = helper.add() product_result = MathHelper.multiply(5, 3) print(f"合計: {sum_result}, 積: {product_result}") # 出力: 合計: 8, 積: 30
解説:
multiplier
: クラス変数です。クラスのすべてのインスタンスで共有されます。add()
: インスタンスメソッドです。オブジェクトの状態 (self.x
,self.y
) を使用して計算を行います。@staticmethod
: デコレータです。静的メソッドであることを示します。静的メソッドは、クラスのインスタンスに依存せず、クラス自体に関連付けられます。MathHelper.multiplier
: クラス変数にアクセスするために使用します。
Problem 9: Class Methods and Static Methods (MathHelper) (English Explanation)
This problem requires you to create a MathHelper
class for performing mathematical calculations. The class should include an instance method called add
that calculates the sum of two numbers, and a static method called multiply
that uses a class variable to calculate the product of two numbers.
The code defines a MathHelper
class with a class variable multiplier
. It includes an instance method add
that takes the object's attributes (self.x
, self.y
) as input and calculates their sum. It also includes a static method multiply
decorated with @staticmethod
. Static methods are associated with the class itself rather than instances of the class, and they can access class variables like MathHelper.multiplier
. An instance of MathHelper
is created, and both methods are called to demonstrate their usage.
問題 10:クラスのプロパティ (TemperatureConverter)
摂氏温度を属性として持ち、華氏温度に変換するゲッターメソッドと、華氏温度から摂氏温度に変換するセッターメソッドを持つ TemperatureConverter
クラスを作成してください。
class TemperatureConverter: def __init__(self, celsius): self._celsius = celsius # 属性をプライベートにする @property def fahrenheit(self): return (self._celsius * 9/5) + 32 @fahrenheit.setter def fahrenheit(self, fahrenheit_temp): self._celsius = (fahrenheit_temp - 32) * 5/9 # TemperatureConverter オブジェクトの作成とメソッド呼び出し converter = TemperatureConverter(25) print(f"摂氏: {converter._celsius}, 華氏: {converter.fahrenheit}") # 出力: 摂氏: 25, 華氏: 77.0 converter.fahrenheit = 68 print(f"華氏: {converter.fahrenheit}, 摂氏: {converter._celsius}") # 出力: 華氏: 68.0, 摂氏: 20.0
解説:
_celsius
: プライベート属性です。アンダースコア_
で始まる属性は、外部からの直接アクセスを避けることを推奨します。@property
: デコレータです。fahrenheit
属性にアクセスすると、get_fahrenheit()
メソッドが自動的に呼び出されます。@fahrenheit.setter
: デコレータです。converter.fahrenheit = value
のようにfahrenheit
属性に値を設定すると、set_fahrenheit(value)
メソッドが自動的に呼び出されます。
Problem 10: Class Properties (TemperatureConverter) (English Explanation)
This problem requires you to create a TemperatureConverter
class with a Celsius temperature attribute, a getter method for converting to Fahrenheit, and a setter method for converting from Fahrenheit back to Celsius.
The code defines a TemperatureConverter
class with a private attribute _celsius
. It uses the @property
decorator to define a getter method for the fahrenheit
attribute, which converts Celsius to Fahrenheit. It also uses the @fahrenheit.setter
decorator to define a setter method that takes a Fahrenheit temperature as input and converts it back to Celsius, updating the _celsius
attribute accordingly. This allows you to access and modify the temperature using the fahrenheit
property in a more intuitive way.