こんにちわ!この記事はPythonの初学者のための内容となっております。
今回は、「継承2」ということで、前回の内容よりもより応用的なコードの記述方法を見ていきます。若干複雑になってきますが、理解できるようになると楽しいですよ!
記事内で示すコードは、オブジェクト指向型プログラミングや継承の書き方を示すものです。直接的に役に立つのではなく、書き方の勉強として参考にしてください。また、プロセス指向のプログラミングとは違う独特の記述方法を学ぶためにも前回の内容もご参照ください!
今回の記事は、このような方向けの内容です。
- 継承についての理解を深めたい
- 継承の具体的な使い方を知りたい
- 前回の内容じゃ物足りない
それでは頑張っていこう!
コンテンツ
プログラミングスクールに関しては下の記事で詳しく記述しています。
こちらで紹介しているスクールは、すべて無料期間がある優良なスクールのみで、特徴を明確にし、読者のニーズに絞って丁寧に解説しました。初めての一歩として、無料説明会に参加してみてください。
継承のおさらい
継承とオーバーライド
継承(Inheritance)とは、同じ性質を再利用することで、楽にプログラムを記述する方法です。また、オーバーライド(override)とは、上乗りという意味で、同じ名前のメソッドを上書きする方法です。
継承の際に、スーパークラスのメソッドを利用するときは、「super()」を書くことで再利用が可能です。これは、コンストラクタなどの特別なメソッドにも利用可能で、メンバ変数が似ているときに有効的です。
コードの例を再確認しよう!
基本構文の確認
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
class Hero: def __init__(self, name, weapon, HP, MP): self.name = name self.weapon = weapon self.HP = HP self.MP = MP def attack(self): print(self.name + "は" + self.weapon + "で基本攻撃をした。") class SuperHero(Hero): def __init__(self, name, weapon, HP, MP, skill): super().__init__(name, weapon, HP, MP) self.skill = skill def attack(self): print(self.name + "は" + self.weapon + "で" + self.skill + "を繰り出した。") if __name__ == "__main__": h1 = Hero("ガッチャマン", "枝", 100, 100) h2 = SuperHero("スパイダーマン", "蜘蛛の糸", 1000, 1000, "蜘蛛アタック") h1.attack() #ガッチャマンは枝で基本攻撃をした。 h2.attack() #スパイダーマンは蜘蛛の糸で蜘蛛アタックを繰り出した。 |
今回は、「Hero」クラスのメンバ変数が4つあり、このメンバ変数は、「SuperHero」クラスでも共通です。そのため、「super()」を用いることで楽に記述できました。
また、この例では、オーバーライドも使っています。「attack」メソッドは、2つのクラスで同じ名前ですが、サブクラスのメソッドが優先して実行されます。継承とオーバーライドを理解していきましょう。
継承の応用
雇用管理プログラムの作成
以下、すべてのプログラムをつなげると実行できます。解説の都合上クラス別に紹介していきます。
従業員
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class Employee: def __init__(self, name, age, gender, code, time): self.name = name self.age = age self.gender = gender self.code = code self.time = time self.min_wage = 1000 def salary(self): salary = self.time * (self.min_wage + self.add_pay) print(self.name + "さんのお給料は" + str(salary) + "円です。") |
クラス「Employee」では、アルバイト、店長、マネージャーのすべての従業員のスーパークラスとなります。従業員は、個人情報に加え、従業員番号や労働時間も管理する必要があります。
また、メソッド「salary」では、各従業員のお給料を計算するメソッドです。メソッド内に、「min_wage」と「add_pay」は、「Employee」クラスのコンストラクタには存在しないですが、別のクラスで定義することになります。それぞれの意味は、最低賃金と能力給です。
アルバイト
1 2 3 4 5 |
class Part(Employee): def __init__(self, name, age, gender, code, time, add_pay = 0): super().__init__(name, age, gender, code, time) self.add_pay = add_pay |
アルバイトに関しては、特にメソッドを定義しませんでした。継承をしているため、コンストラクタをスーパークラスのものを用いて楽に記述しています。
アルバイトなので、能力給を示す「add_pay」はデフォルトで0円です。
店長
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
class Store_manager(Employee): def __init__(self, name, age, gender, code, time, add_pay = 500): super().__init__(name, age, gender, code, time) self.add_pay = add_pay self.partners = [] def add_partner(self, *partners): for partner in partners: if partner not in self.partners: self.partners.append(partner) print(partner.name + "さんを" + self.name + "店長のパートナーとして登録しました。") else: print(partner.name + "さんの名前は既に登録済みです。") return 0 def del_partner(self, part): if part in self.partners: self.partners.remove(part) print(part.name + "さんの登録を削除しました。") else: print(part.name + "さんは登録されていませんでした。") return 0 def show_store(self): print(self.name + "店舗では" + str(len(self.partners)) + "人のアルバイトがいる。") |
「Store_manager」クラスでは、店長を示しており、各店長(店舗)には、数人のアルバイトがいるという想定です。そのため、メソッド「add_partner」と「del_partner」を定義しました。「add_partner」には、引数を可変長引数にして、1行で何人も同時に登録できるような工夫を施しています。
追加や削除機能は基本的なプログラミング(CRUD機能)なのでぜひともマスターしたいですね。可変長引数については以下の記事を参考にしてください。
マネージャー
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
class Manager(Employee): def __init__(self, name, age, gender, code, time, add_pay = 1000): super().__init__(name, age, gender, code, time) self.add_pay = add_pay self.store_managers = [] def add_store_manager(self, *store_managers): for store_manager in store_managers: if store_manager not in self.store_managers: self.store_managers.append(store_manager) print(store_manager.name + "さんを店長として登録しました。") else: print(store_manager.name + "さんは登録されていませんでした。") return 0 #def del_store_manager(self, store_manager):(問題で使用) def show_storemanager(self): print(self.name + "マネージャーは" + str(len(self.store_managers)) + "店舗を管理している。") |
「Manager」クラスでも、各店舗を管理することを想定しているので、「add_store」、「del_store_manager」(※問題で使用)を定義しています。
今までの構造としてはこのようになります。マネージャーは数店舗(数人の店長)を管理しており、各店長は、数人のアルバイトを雇用している状態です。
今思ったのですが、すべてのクラスで、メンバ変数の「add_pay」もスーパークラスのコンストラクタに入れてもいいと思います。ただ、書き方は自由なので問題はないです。
メイン関数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
if __name__ == "__main__": part1 = Part("part1", 21, "M", 1000001, 20, 0) part2 = Part("part2", 22, "M", 1000002, 25, 0) part3 = Part("part3", 22, "F", 1000003, 40, 20) part4 = Part("part4", 23, "F", 1000004, 0, 10) store_manager1 = Store_manager("store_manager1", 41, "M", 1001, 160, 500) store_manager2 = Store_manager("store_manager2", 45, "M", 1002, 160, 600) manager = Manager("manager", 50, "M", 1, 170, 1200) store_manager1.add_partner(part1, part2, part3) #part1さんをstore_manager1店長のパートナーとして登録しました。 #part2さんをstore_manager1店長のパートナーとして登録しました。 #part3さんをstore_manager1店長のパートナーとして登録しました。 store_manager2.add_partner(part4) #part4さんをstore_manager2店長のパートナーとして登録しました。 manager.add_store_manager(store_manager1, store_manager2) #store_manager1さんを店長として登録しました。 #store_manager2さんを店長として登録しました。 store_manager1.show_store() #store_manager1店舗では3人のアルバイトがいる。 store_manager2.show_store() #store_manager2店舗では1人のアルバイトがいる。 manager.show_storemanager() #managerマネージャーは2店舗を管理している。 store_manager1.del_partner(part2) #part2さんの登録を削除しました。 store_manager1.show_store() #store_manager1店舗では2人のアルバイトがいる。 part1.salary() #part1さんのお給料は20000円です。 store_manager1.salary() #store_manager1さんのお給料は240000円です。 manager.salary() #managerさんのお給料は374000円です。 |
うげぇぇー!長すぎぃぃぃ!
確かに長いですが、すべてのクラス、メソッドの確認をしています。プログラムの実行結果は思惑通りになっていてうまくできていますね。また、お給料が生々しいのも面白いところです笑。
全体のコード
こちらが全体のコードになります。
質問などがあれば、記事内でコメントしたり、お問い合わせしてくれると嬉しいです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
class Employee: def __init__(self, name, age, gender, code, time): self.name = name self.age = age self.gender = gender self.code = code self.time = time self.min_wage = 1000 def salary(self): salary = self.time * (self.min_wage + self.add_pay) print(self.name + "さんのお給料は" + str(salary) + "円です。") class Part(Employee): def __init__(self, name, age, gender, code, time, add_pay = 0): super().__init__(name, age, gender, code, time) self.add_pay = add_pay class Store_manager(Employee): def __init__(self, name, age, gender, code, time, add_pay = 500): super().__init__(name, age, gender, code, time, add_pay) self.add_pay = add_pay self.partners = [] def add_partner(self, *partners): for partner in partners: if partner not in self.partners: self.partners.append(partner) print(partner.name + "さんを" + self.name + "店長のパートナーとして登録しました。") else: print(partner.name + "さんの名前は既に登録済みです。") return 0 def del_partner(self, part): if part in self.partners: self.partners.remove(part) print(part.name + "さんの登録を削除しました。") else: print(part.name + "さんは登録されていませんでした。") return 0 def show_store(self): print(self.name + "店舗では" + str(len(self.partners)) + "人のアルバイトがいる。") class Manager(Employee): def __init__(self, name, age, gender, code, time, add_pay = 1000): super().__init__(name, age, gender, code, time) self.add_pay = add_pay self.store_managers = [] def add_store_manager(self, *store_managers): for store_manager in store_managers: if store_manager not in self.store_managers: self.store_managers.append(store_manager) print(store_manager.name + "さんを店長として登録しました。") else: print(store_manager.name + "さんは登録されていませんでした。") return 0 #def del_store_manager(self, store_manager):(問題で使用) def show_storemanager(self): print(self.name + "マネージャーは" + str(len(self.store_managers)) + "店舗を管理している。") if __name__ == "__main__": part1 = Part("part1", 21, "M", 1000001, 20, 0) part2 = Part("part2", 22, "M", 1000002, 25, 0) part3 = Part("part3", 22, "F", 1000003, 40, 20) part4 = Part("part4", 23, "F", 1000004, 0, 10) store_manager1 = Store_manager("store_manager1", 41, "M", 1001, 160, 500) store_manager2 = Store_manager("store_manager2", 45, "M", 1002, 160, 600) manager = Manager("manager", 50, "M", 1, 170, 1200) store_manager1.add_partner(part1, part2, part3) store_manager2.add_partner(part4) manager.add_store_manager(store_manager1, store_manager2) store_manager1.show_store() store_manager2.show_store() manager.show_storemanager() store_manager1.del_partner(part2) store_manager1.show_store() part1.salary() store_manager1.salary() manager.salary() |
まとめ
今回は、過去一長いプログラムを紹介しました。オブジェクト指向型プログラミングや継承を用いたプログラミングの記述例を参考にしていただけると嬉しいです。
オブジェクト指向型プログラミングでは、現実世界をプログラムで再現することが基本です。今回の例では、雇用管理プログラムということで、「従業員」、「アルバイト」、「店長」、「マネージャー」がそれぞれどのような関係やになっているのかを考える必要がありました。
また、継承に関しては、従業員の基本的なデータ(名前、年齢、労働時間など)をメンバ変数として、定義する方法も今回で学べたと思います。継承を用いれば、いちいちメンバ変数のセッターを準備する必要がなくなり、コードを短く記述することが可能です。
今回で、1通りプログラミングの基本は終わった感じがするので、今後はPythonを使って面白いことを紹介していこうと思っております。
今後もよろしくお願いしますね!!
本日の理解度調査
今日の最後に理解度調査をします!!
どうすれば正しくなるのか考えてみてね!!
Q. 「Manager」クラスのメソッド「del_store_manager」を完成させよ。
1 2 3 4 5 6 7 |
def del_store_manager(self, store_manager): if ???: self.store_managers.remove(store_manager) print(store_manager.name + "さんの登録を削除しました。") else: print(store_manager.name + "さんは登録されていませんでした。") return 0 |
※実際には、店舗を削除した場合、そこにいるアルバイトの存在を確認する必要があります。(たぶん)
正解は。。。
1 |
if store_manager in self.store_managers: |
わかったかな??正解出来たら今回の項目は完璧だね!!
最後まで記事を読んでいただきありがとうございます!
昔、自分が参考にしていたプログラミングについての書籍を紹介します。
非常にわかりやすい書籍となっていますのでご確認ください。
プログラミングスクールに関しては下の記事で詳しく記述しています。
こちらで紹介しているスクールは、すべて無料期間がある優良なスクールのみで、特徴を明確にし、読者のニーズに絞って丁寧に解説しました。初めての一歩として、無料説明会に参加してみてください。