第6章: Pythonicなオブジェクト指向プログラミング

Pythonのオブジェクト指向プログラミング(OOP)は、他の言語と考え方は似ていますが、よりシンプルで柔軟な構文を持っています。この章では、クラスの定義から継承、そしてPython特有の「マジックメソッド」まで、その基本を学びます。

`class`の定義とインスタンス化

Pythonでは、classキーワードを使ってクラスを定義します。JavaやC++のように波括弧{}は使わず、インデントでブロックを示します。非常にシンプルです。

クラスを定義したら、関数を呼び出すようにクラス名()と書くことで、そのクラスのインスタンス(オブジェクト)を生成できます。

dog1.py
python dog1.py

コンストラクタ (`__init__`) と `self`

Pythonのクラスでは、__init__という名前の特殊なメソッドがコンストラクタの役割を果たします。このメソッドは、クラスがインスタンス化される際に自動的に呼び出されます。

メソッドの最初の引数にはselfを書くのが慣習です。これはインスタンス自身への参照であり、JavaやC++のthisに相当します。ただし、Pythonではselfを明示的に引数として記述する必要があります。

dog2.py
python dog2.py

インスタンス変数とクラス変数

Pythonのクラスには、2種類の変数があります。

  • インスタンス変数: self.変数名のように__init__内などで定義され、各インスタンスに固有の値を持ちます。上の例のnameageがこれにあたります。
  • クラス変数: クラス定義の直下に書かれ、そのクラスから作られた全てのインスタンスで共有されます。
dog3.py
python dog3.py

メソッドの定義

クラス内で定義される関数をメソッドと呼びます。インスタンスのデータ(インスタンス変数)を操作するために使用します。 メソッドを定義する際も、最初の引数には必ずselfを指定する必要があります。これにより、メソッド内からselfを通じてインスタンス変数にアクセスできます。

dog4.py
python dog4.py

クラスメンバーの型アノテーション

型安全性を高めるために、クラス変数やインスタンス変数にも型アノテーション(型ヒント)を付けることができます。

  • クラス変数: 変数名: 型 = 値 のように記述します。
  • インスタンス変数: __init__内で self.変数名: 型 = 値 のように記述するか、クラス直下で 変数名: 型 と宣言だけしておくこともできます。
dog5.py
python dog5.py

継承

あるクラスの機能を引き継いだ新しいクラスを作成することを継承と呼びます。Pythonでは、クラス定義の際に()内に親クラス(基底クラス)を指定することで継承を行います。

子クラス(派生クラス)は親クラスのメソッドや変数を全て利用でき、必要に応じて上書き(オーバーライド)することも可能です。親クラスのメソッドを呼び出したい場合はsuper()を使います。

dog6.py
python dog6.py

基本的なマジックメソッド (`__str__`, `__repr__`)

__init__のように、アンダースコア2つで囲まれた特殊なメソッドをマジックメソッド(またはダンダーメソッド)と呼びます。これらを定義することで、Pythonの組み込み関数の挙動をカスタマイズできます。

  • __str__(self)
    • print()関数やstr()でオブジェクトを文字列に変換する際に呼び出されます。
    • 目的は、人間にとって読みやすい、非公式な文字列表現を返すことです。
  • __repr__(self)
    • repr()関数で呼び出されるほか、__str__が定義されていない場合のprint()や、インタラクティブシェルでオブジェクトを評価した際に使われます。
    • 目的は、曖昧さのない、公式な文字列表現を返すことです。理想的には、その文字列を評価すると同じオブジェクトを再作成できるような表現(例: MyClass(arg1=1, arg2='B'))が望ましいです。
dog7.py
python dog7.py

この章のまとめ

  • クラス定義: class ClassName: で定義する。
    • コンストラクタ: __init__(self, ...) メソッドで、インスタンス化の際に初期化処理を行う。
    • self: インスタンス自身を指す参照。メソッドの第一引数として必ず記述する。
    • 変数: インスタンスごとに持つインスタンス変数と、全インスタンスで共有するクラス変数がある。
    • 継承: class Child(Parent): でクラスの機能を引き継ぐ。親のメソッドはsuper()で呼び出せる。
    • マジックメソッド: __str____repr__などを定義することで、オブジェクトの振る舞いをカスタマイズできる。

この章のまとめ

この章では、Pythonにおけるオブジェクト指向プログラミングの基本を学びました。

  • クラスとインスタンス: classキーワードでクラスという「設計図」を定義し、クラス名()でインスタンスという「実体」を作成します。
  • __init__self: __init__はインスタンス化の際に呼ばれるコンストラクタです。第一引数のselfはインスタンス自身を指し、self.変数名の形でインスタンスごとにユニークなインスタンス変数を定義します。
  • クラス変数: クラス直下に定義され、全てのインスタンスで共有される変数です。
  • メソッド: クラス内で定義される関数で、インスタンスの振る舞いを表します。メソッドの第一引数も必ずselfです。
  • 継承: class 子クラス(親クラス):と書くことで、親クラスの機能を引き継いだ新しいクラスを作成できます。super()を使うことで、親クラスのメソッドを呼び出せます。
  • マジックメソッド: __str____repr__のように__で囲まれた特殊なメソッドで、print()などの組み込み関数の挙動をカスタマイズできます。

PythonのOOPは、JavaやC++に比べてシンプルで直感的な構文が特徴です。しかし、その裏側にある「すべてがオブジェクトである」という思想は一貫しており、非常に強力なプログラミングパラダイムです。

練習問題1: `Book`クラスの作成

書籍の情報を管理するBookクラスを作成してください。

要件:

  1. インスタンス化する際に、title(タイトル)とauthor(著者)を引数で受け取る。
  2. info()というメソッドを持ち、呼び出すと「{タイトル}」- {著者}という形式の文字列を返す。
  3. print()でインスタンスを直接表示した際に、info()メソッドと同じ文字列が表示されるようにする。
practice6_1.py
python practice6_1.py

練習問題2: 継承を使った`EBook`クラスの作成

問題1で作成したBookクラスを継承して、電子書籍を表すEBookクラスを作成してください。

要件:

  1. Bookクラスを継承する。
  2. インスタンス化の際に、titleauthorに加えてfile_size(ファイルサイズ、MB単位)も引数で受け取る。
  3. info()メソッドをオーバーライドし、呼び出すと「{タイトル}」- {著者} (ファイルサイズ: {file_size}MB)という形式の文字列を返すように変更する。
practice6_2.py
python practice6_2.py