1. 継承の基本
class 子クラス(親クラス): と書くと、親クラスの属性・メソッドをすべて引き継ぎます。
共通部分を親クラスに書き、差分だけ子クラスで追加・上書きするのが継承の考え方です。
継承を使う主なメリットは コードの重複を減らせること です。 医師・看護師・技師など職種が増えても、共通の「氏名・年齢・部署」の管理ロジックは 親クラスに1つ書けば済みます。後から仕様が変わっても親クラスを直すだけで全職種に反映されます。
💡 super() とは? 親クラスを参照するための関数です。super().__init__(...) で親クラスの初期化処理を実行します。これを忘れると親の属性(self.name など)が設定されず、親のメソッドを使おうとしたときに AttributeError になります。
📋 継承ツリーのイメージ:
MedicalStaff(親) ├── Doctor(子) … introduce() を継承 + diagnose() を追加 └── Nurse(子) … introduce() を継承 + administer() を追加
共通の introduce() は親クラスに1つ書けば、すべての子クラスで使えます。
2. メソッドのオーバーライド
子クラスで親クラスと同じ名前のメソッドを定義すると、上書き(オーバーライド)されます。
super().メソッド名() で親の処理を呼び出した上で追加処理を加えることもできます。
オーバーライドは「親の動作では不十分なとき」に使います。
たとえば Doctor の業務内容は MedicalStaff の標準業務とは異なるため、
work() を専用の内容で上書きします。
💡 super() の使い分け:
- 完全に置き換えたい →
super()なしで新しい処理だけ書く(例:Doctor.work()) - 親の処理を活かして拡張したい →
super().work()を先に呼び、その後に追加処理を書く(例:ChiefDoctor.work())
🔑 ポリモーフィズム(多態性)とは、同じメソッド名で呼び出しても、オブジェクトの種類によって異なる動作をすることです。staff.work()・doctor.work()・chief.work() はすべて work() という名前でも、それぞれ違う処理が実行されます。「インターフェースを統一しつつ実装を分ける」というオブジェクト指向設計の核心です。
3. isinstance() と issubclass()
isinstance(obj, クラス) でオブジェクトが特定クラス(またはその子クラス)のインスタンスかを確認できます。
型の判定や分岐処理でよく使います。
issubclass(子クラス, 親クラス) はオブジェクトではなくクラス同士の関係を調べます。
「このクラスはあのクラスを継承しているか?」を確認するときに使います。
💡 isinstance() vs type() の違い:
isinstance(doc, MedicalStaff)→ True(継承関係を含めて判定する)type(doc) == MedicalStaff→ False(厳密に同じ型のみ判定する)
「Doctor も MedicalStaff の一種である」という継承の意味を正しく扱えるため、通常は isinstance() を使います。
4. 継承でニューラルネット層を表現する
📌 AI/PyTorch の文脈に触れる内容です・高難易度のためスキップ可: 今はピンとこなくても大丈夫です。PyTorch や AI資格の学習を始めたときに「あ、継承ってこういう場面で使うんだ」と戻ってくるつもりで眺めるだけでも構いません。
PyTorch の各層(nn.Linear、nn.Conv2d)はすべて nn.Module という基底クラスを継承しています。
このレッスンで学んだ継承と全く同じパターンで作られています。ここでは純粋な Python でその仕組みを再現してみましょう。
🔑 このコードに登場する新しい構文:
raise NotImplementedError("...")— 「このメソッドはサブクラスで必ず実装してください」という意味のエラーを意図的に発生させます。実装し忘れた場合にすぐ気づけるよう、抽象メソッドの代替として使う定番パターンです。def __call__(self, x):— インスタンスをnet(入力)のように関数として呼び出したときに自動で実行される特殊メソッド(L15 で詳しく扱います)。PyTorch ではmodel(x)と書くと内部でこれが動き、forward()を呼び出します。getattr(obj, "属性名")—obj.属性名と同じ意味ですが、属性名を文字列として渡せます。ループ内で属性名を動的に変えたいときに使います(例:for name in ["conv1", "fc1"])。
📊 順伝播(forward pass)の呼び出しの流れ:
net("画像入力")と書いて呼び出す- Pythonが自動的に
net.forward(x)を実行する forwardの中でconv1 → fc1 → fc2の順に処理が流れる- 最後の
fc2の結果がoutputとして返ってくる
net("入力") と1行書くだけで、定義した層が順番に自動で呼ばれます。これは実際の PyTorch モデルの動き方と全く同じ構造です。
5. 練習問題
PersonからDoctorを継承する
Person クラス(name・age・greet())を親として、Doctor クラスを作成してください。Doctor は追加属性 specialty(専門)を持ち、greet() をオーバーライドして「○○医師(□□専門)です」と表示します。
ヒントを見る(答え+解説)
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
print(f"こんにちは、{self.name}({self.age}歳)です")
class Doctor(Person):
def __init__(self, name, age, specialty):
super().__init__(name, age)
self.specialty = specialty
def greet(self):
print(f"{self.name}医師({self.specialty}専門)です")
doc = Doctor("佐藤一郎", 42, "循環器科")
doc.greet()
# → 佐藤一郎医師(循環器科専門)です
super().__init__(name, age) で親クラスの初期化処理を呼び出し、子クラス独自の属性を追加します。greet() をオーバーライドすることで親とは違う動作に差し替えられます。
職種ごとに分岐処理
Doctor と Nurse のリストから、isinstance() を使って職種ごとに処理を分けてください。Doctorは「診察可能」、Nurseは「処置可能」と表示します。
ヒントを見る(答え+解説)
class MedicalStaff:
def __init__(self, name):
self.name = name
class Doctor(MedicalStaff):
pass
class Nurse(MedicalStaff):
pass
staff_list = [
Doctor("佐藤医師"),
Nurse("田中看護師"),
Doctor("山田医師"),
Nurse("鈴木看護師"),
]
for person in staff_list:
if isinstance(person, Doctor):
print(f"{person.name}: 診察可能")
elif isinstance(person, Nurse):
print(f"{person.name}: 処置可能")
# → 佐藤医師: 診察可能 / 田中看護師: 処置可能 / ...
isinstance(オブジェクト, クラス名) はそのオブジェクトが指定クラスのインスタンスかどうかを判定します。継承関係があっても正しく判定でき、医療システムでの職種別処理によく使います。
super() で親の処理を流用
Patient クラスに report() メソッドがあります。ICUPatient クラスで report() をオーバーライドし、super().report() を呼んだ後に「ICU管理中: □□」と追記してください。
ヒントを見る(答え+解説)
class Patient:
def __init__(self, name, diagnosis):
self.name = name
self.diagnosis = diagnosis
def report(self):
print(f"患者: {self.name}, 診断: {self.diagnosis}")
class ICUPatient(Patient):
def __init__(self, name, diagnosis, device):
super().__init__(name, diagnosis)
self.device = device
def report(self):
super().report()
print(f"ICU管理中: {self.device}")
icu = ICUPatient("田中太郎", "重症肺炎", "人工呼吸器")
icu.report()
# → 患者: 田中太郎, 診断: 重症肺炎
# → ICU管理中: 人工呼吸器
super().report() で親クラスの処理をそのまま実行した後、子クラス独自の追加情報を出力します。コードを重複させずに機能を拡張できる継承の典型的な使い方です。
まとめ
このレッスンのポイント
class 子(親):で親クラスの属性・メソッドをすべて引き継ぐsuper().__init__(...)で親の初期化を実行する(忘れずに!)- 子クラスで同名のメソッドを定義するとオーバーライドされる
super().メソッド()で親の処理を呼び出しながら追加処理できるisinstance(obj, クラス)は親クラスに対してもTrueを返す- PyTorchの
nn.Linear,nn.Conv2dはすべてnn.Moduleを継承している
自由に試してみましょう:
完了するとトップページに進捗が表示されます
