お役立ち

Pythonのクラス(コンストラクタ・継承・抽象メソッドなど…)

  • このエントリーをはてなブックマークに追加

クラスの定義

Pythonでは、__init__メソッドがコンストラクタです。
ここに、初期化処理を書きます。

class Animal:
    def __init__(self, name, age):
        self.name = name
        self.age = age
animal = Animal("Hoge", 3)

クラスの継承

Pythonでクラスの継承はクラス名(親クラス)と書きます。
さきほどのAnimalクラスを継承してDogクラスを作成します。

class Dog(Animal):
    def bark(self):
        print("わんわん")
dog = Dog("ぽち",2)
dog.bark()
# わんわん

メソッドをオーバーライド

メソッドのオーバーライドは子クラス同じメソッド名の関数を定義するだけです。
barkのメソッドが”わんわん”だったのを”bow bow”に書き換えてみます。

class EngDog(Dog):
    def bark(self):
        print("bow bow")
dog = EngDog("ぽち",2)
dog.bark()
# bow bow

親クラスのコンストラクタに処理を追加

親クラスのコンストラクタに処理を追加したい場合は、__init__をオーバーライドすることで行います。

class Dog(Animal):
    def __init__(self, name, age, owner):
        Animal.__init__(self, name, age)
        self.owner = owner
    def bark(self):
        print("わんわん")
dog = Dog("ぽち", 2, "田中さん")
dog.bark()
# わんわん

多重継承

Pythonでは、クラスの多重継承がサポートされています。

class Animal:
    def __init__(self, name, age):
        self.name = name
        self.age = age
class Flyer:
    def fly(self):
        print("ぴょんぴょん")
class Bird(Animal,Flyer):
    def bark(self):
        print("ぽっぽ")
bird = Bird("公園のはと",2)
bird.fly()
# ぴょんぴょん
bird.bark()
# ぽっぽ

super関数

super関数は、親クラスのインスタンスを呼び出す関数です。
親クラスのメソッドにアクセスする際によく利用します。

super関数をコンストラクタで使う

super関数を利用して、
親クラスのコンストラクタを呼び出して
コンストラクタに処理を追加する書き方もあります。

# Python3の書き方
class Dog(Animal):
    def __init__(self, name, age):
        super().__init__(name, age, owner)
                self.owner = owner
    def bark(self):
        print("わんわん")
dog = Dog("ぽち",2,"田中さん")
dog.bark()

Python2の場合は、super関数の使い勝手がわるいです。
Pythonではメンバメソッドの引数にselfを渡すなど、
処理を明示する思想にのっとてこのような書き方になっているのでしょう。
サンプルコードの注意して書きましょう。

# Python2の書き方
class Animal(object):# ←注意1:objectを明記する
    def __init__(self, name, age):
        self.name = name
        self.age = age
class Dog(Animal):
    def __init__(self, name, age, owner):
        super(Dog, self).__init__(name, age)# ←注意2:DogとAnimalを間違わない
        self.owner = owner
        def bark(self):
        print("わんわん")
dog = Dog("ぽち",2,"田中さん")
dog.bark()

抽象メソッド

抽象クラスをPythonで実装するためには、
標準モジュールabc(Abstract Base Class)を利用します。

from abc import ABCMeta, abstractmethod
class HogeInterface(metaclass=ABCMeta):
    def hoge(self):
        return "hoge"
    @abstractmethod
    def show(self):
        pass

抽象メソッドをPythonで書くために重要なのは次の2点です。

  • ABCMetaをmetaclassにする
  • 抽象メソッドに@abstractmethodをつける

抽象メソッドを実装しないと

抽象メソッドを実装しないとどうなるかを試してみます。


# HogeInterfaceを継承(showを実装してない)
class Fuga(HogeInterface):
    pass
Fuga()
TypeError: Can't instantiate abstract class Fuga with abstract methods show

ちゃんとshowメソッドを実装してくださいと例外が発生します。
これは、@abstractmethodが重要です。

@abstractmethodを忘れると…

試しに、@abstractmethodを書かずに実装してみます。

from abc import ABCMeta, abstractmethod
class HogeInterface(metaclass=ABCMeta):
    def hoge(self):
        return "hoge"
    def show(self):
        pass
class Fuga(HogeInterface):
    pass
Fuga()

すると、例外が発生しません。
なので、抽象メソッドを実装するときは、
@abstractmethodを忘れずにつけましょう。

Pythonでインターフェイス

Pythonはインターフェイスという概念は明示的には存在しません。
しかし、Pythonでインターフェイスを実現することはできます。
Pythonでは、「抽象メソッドだけのクラス=インターフェイス」となります。
なので、前述の抽象メソッドを利用することで
Pythonでもインターフェイスを実装できます。
ほかの言語でクラスとインターフェイスを区別する必要があるのは、
多重継承の可否を明示する意味があります。
多くの言語では、クラスの多重継承は禁止となっています。
その代わりに用意されているのが多重継承可能なインターフェイスです。
ただし、Pythonでは、クラスの多重継承をサポートしています。
抽象メソッドだけのクラスとインターフェイスを区別する必要がないので、
Pythonでは、インターフェイスが明示されていません。

  • このエントリーをはてなブックマークに追加