はじめに
こんにちは。孔子の80代目子孫兼アプリケーションサービス部の孔です。前回の記事ではオブジェクト指向プログラミングについて見てみましたね。そして、PythonではClass
というものを使ってオブジェクトを作成するとの話をしました。
今回から3回に分けて、そのClassの使用方法を具体的に見てみましょう。まずはClassの定義方法からです。
Classの定義
まずは復習になります。オブジェクトは「データ」と「処理」の集まりであること、そしてPythonではオブジェクトをclass
という予約語を使って定義するとの話をしました。余談ですが、「データ」のことを「属性(=プロパティ、Property)」、「処理」のことを「メソッド(Method)」と呼ぶことが多いです。今後、「属性」や「メソッド」という言葉が出てきたら、それぞれ何かのクラスの中で定義された「データ」と「処理」を指してるんだなと思ってください。
それではオブジェクトを作ってみましょう。今回は飲食店で、各テーブルごとの注文に関するオブジェクトを作ってみます。飲食店には、テーブルが複数あって、それぞれのテーブルで注文やお客様の管理をしています。今回は、テーブルごとの注文に関するオブジェクトは以下のデータを必要とするオブジェクトとします。
- テーブル番号
- 注文した料理
- 滞在時間
そして、以下の処理をすることとします。
- 注文を追加する
- 滞在時間を出力する
- お会計金額を出力する
上記の実装を、以下のようにすることができそうです。コードの分析はこの後に続きますのでまずは軽く読んでみてください。
import time class Table: # テーブルごとの注文に関するオブジェクト def __init__(self, table_num: int): # テーブル番号, 注文した料理, 滞在時間のデータを作る self.table_num = table_num self.order = [] self.start_time = time.time() def add_order(self, order: list): self.order.extend(order) return None def get_stay_time(self): return time.time() - self.start_time def billing(self): amount = self.__calculate_amount() return amount def __calculate_amount(self): menu = Menu.get_menu() amount = 0 for ordered in self.order: amount += menu[ordered] return amount class Menu: # メニューに関するオブジェクト @classmethod def get_menu(cls): menu = { "beef": 1000, "chicken": 800, "pork": 900 } return menu # お客様が10番テーブルに着席したよ! table = Table(10) # 注文内容は豚肉と牛肉だよ! table.add_order(["pork", "beef"]) # 着席してからどれくらい時間が経ったのか確認するよ! table.get_stay_time() # お会計だよ! table.billing()
それでは、コードの中身を見てClassは何から定義されるのか見てみましょう。以下の順番で見ていきます。
__init__
とは- selfとは
- アクセス修飾子(Access Modifier)とは
- クラスメソッド(Class Method)とは
initとは:コンストラクタの紹介
上から読んでみて、まず普段あまり目にしないものがありますね。
class Table: def __init__(self, table_num: int): # これなに?
コンストラクタと呼ばれるこの__init__
ですが、役割は「インスタンスが生成されるときに呼び出される処理」となります。以下のコードをみてください。
class Test: def __init__(self): print("Testのインスタンスが生成されました") test_1 = Test() # Testのインスタンスが生成されました test_2 = Test() # Testのインスタンスが生成されました test_3 = Test() # Testのインスタンスが生成されました
Test
クラスからtest_1, 2, 3といったインスタンスを生成するたびに__init__
で定義した処理が走り、print
関数が実行されています。インスタンスを作成する際には初期値を設定したり、決まった共通の処理をやるなど、最初にやっておく必要がある処理があることがあります。その際には__init__
からコンストラクタを定義しましょう!
selfとは:インスタンス自身を指す慣用句
その次に目立つのがこのself
というものです。
import time class Table: # テーブルごとの注文に関するオブジェクト def __init__(self, table_num: int): # テーブル番号, 注文した料理, 滞在時間のデータを作る self.table_num = table_num self.order = [] self.start_time = time.time() def add_order(self, order: list): self.order.extend(order) return None def get_stay_time(self): return time.time() - self.start_time def billing(self): amount = self.__calculate_amount() return amount def __calculate_amount(self): menu = Menu.get_menu() amount = 0 for ordered in self.order: amount += menu[ordered] return amount
self
は、「インスタンス自身」という意味となります。例えばself.table_num
はそのインスタンス自身の「table_num」というデータ、billing
メソッドで使われているself.__calculate_amount()
はインスタンス自身が持っている「__calculate_amount」というメソッドを呼び出す、といった意味になります。
これのおかげで、各インスタンスごとにデータを管理することができるようになります。以下のコードをみてください。
class Animal: def __init__(self, num_of_legs): # num_of_legs = 動物の足の本数 self.num_of_legs = num_of_legs cat = Animal(4) cat.num_of_legs # 4 spider = Animal(8) spider.num_of_legs # 8 centipede = Animal(100) # ムカデ。漢字で「百足」なので一応100に設定 centipede.num_of_legs # 100
このように、インスタンスを何個生成しても、足の本数が知りたければオブジェクトに対して「num_of_legs」を参照すると、それぞれのインスタンスが持っている値を取得することができるようになります。これがself
の役割となります。
クラスの中で定義される全てのメソッドは第一引数にインスタンス自身を指す引数を指定します。そのため、別にself
じゃなくmyself
やwatashi
と命名してもいいですが、慣用的にself
と付けることが一般的です。
最後に
今回、結構な分量になってきましたので、ここで一旦区切ります!次回、続きで以下の紹介をします。
- アクセス修飾子とは
- クラスメソッド(Class Method)とは
シリーズ一覧
- 第1章:デザインパターンを学ぶための基礎知識