abc --- 抽象基底クラス

ソースコード: Lib/abc.py


このモジュールは Python に PEP 3119 で概要が示された 抽象基底クラス (ABC) を定義する基盤を提供します。なぜこれが Python に付け加えられたかについてはその PEP を参照してください。 (ABC に基づいた数の型階層を扱った PEP 3141 と numbers モジュールも参照してください。)

collections モジュール には、抽象基底クラス から派生するいくつかの具象クラスがある。もちろん、これらはさらに派生させることができる。さらに、 collections.abc サブモジュールには、クラスやインスタンス が特定のインターフェース 、たとえば 、 hashable であるか、 mapping であるかをテストするために使用できる抽象基底クラス があります。

このモジュールは、 抽象基底クラスを定義するためのメタクラス ABCMeta と、 継承を利用して抽象基底クラスを代替的に定義するヘルパークラス ABC を提供します。

class abc.ABC

メタクラスとして ABCMeta を持つヘルパークラスです。このクラスを使うことで、ABC を継承するだけで抽象基底クラスを作成でき、しばしば混乱しがちなメタクラスの使用を避けることができます。例えば:

from abc import ABC

class MyABC(ABC):
    pass

ABC の型は ABCMeta なので、ABC を継承する場合も、メタクラスを使う際の通常の注意が必要です。 多重継承ではメタクラスが競合する場合があります。 また、metaclass キーワードに ABCMeta を直接指定して、抽象基底クラスを定義することもできます。

from abc import ABCMeta

class MyABC(metaclass=ABCMeta):
    pass

Added in version 3.4.

class abc.ABCMeta

抽象基底クラス(ABC)を定義するためのメタクラス。

ABC を作るときにこのメタクラスを使います。ABC は直接的にサブクラス化することができ、ミックスイン(mix-in)クラスのように振る舞います。また、無関係な具象クラス(組み込み型でも構いません)と無関係な ABC を "仮想的サブクラス" として登録できます -- これらとその子孫は組み込み関数 issubclass() によって登録した ABC のサブクラスと判定されますが、登録した ABC は MRO (Method Resolution Order, メソッド解決順)には現れませんし、この ABC のメソッド実装が(super() を通してだけでなく)呼び出し可能になるわけでもありません。 [1]

メタクラスが ABCMeta のクラスには、次のメソッドがあります。

register(subclass)

subclass を "仮想的サブクラス" としてこの ABC に登録します。たとえば:

from abc import ABC

class MyABC(ABC):
    pass

MyABC.register(tuple)

assert issubclass(tuple, MyABC)
assert isinstance((), MyABC)

バージョン 3.3 で変更: クラスデコレータとして使うことができるように、登録されたサブクラスを返します。

バージョン 3.4 で変更: register() の呼び出しを検出するには、get_cache_token() 関数を使えます。

また、次のメソッドを抽象基底クラスの中でオーバーライドできます:

__subclasshook__(subclass)

(クラスメソッドとして定義しなければなりません。)

subclass がこの ABC のサブクラスとみなされるか調べます。 このメソッドで issubclass() の動作をさらにカスタマイズすれば、ABC のサブクラスとみなしたいクラスごとに register() を呼ぶ必要がなくなります。 (このクラスメソッドは、ABC の __subclasscheck__() メソッドから呼び出されます。)

このメソッドは True、False、NotImplemented のいずれかを返す必要があります。 True を返すと、subclass はこの ABC のサブクラスとみなされます。 False を返すと、通常ならサブクラスであっても、subclass はこの ABC のサブクラスとはみなされません。 NotImplemented を返すと、通常の仕組みでサブクラスの検査を続けます。

この概念のデモとして、次の ABC 定義の例を見てください:

class Foo:
    def __getitem__(self, index):
        ...
    def __len__(self):
        ...
    def get_iterator(self):
        return iter(self)

class MyIterable(ABC):

    @abstractmethod
    def __iter__(self):
        while False:
            yield None

    def get_iterator(self):
        return self.__iter__()

    @classmethod
    def __subclasshook__(cls, C):
        if cls is MyIterable:
            if any("__iter__" in B.__dict__ for B in C.__mro__):
                return True
        return NotImplemented

MyIterable.register(Foo)

ABC MyIterable は、イテラブルの標準的なメソッド __iter__() を抽象メソッドとして定義しています。 ここで定義した実装は、サブクラスから呼び出すこともできます。 get_iterator() メソッドも抽象基底クラス MyIterable の一部ですが、抽象クラスではない派生クラスでオーバーライドする必要はありません。

ここで定義したクラスメソッド __subclasshook__() は、__dict__ に __iter__() メソッドを持つクラスを MyIterable とみなします。 また、__mro__ リストからたどれる基底クラスのいずれかがそのメソッドを持つ場合も、同様にみなします。

最後の行では、__iter__() メソッドを定義していない Foo も、MyIterable の仮想的サブクラスにしています (Foo は __len__() と __getitem__() に基づく古いイテラブルプロトコルを使っています)。 ただし、これによって get_iterator が Foo のメソッドとして使えるようになるわけではないので、別途定義しています。

abc モジュールは、次のデコレータも提供します。

@abc.abstractmethod

抽象メソッドを示すデコレータです。

このデコレータを使うには、クラスのメタクラスが ABCMeta またはその派生クラスである必要があります。 メタクラスが ABCMeta から派生しているクラスは、すべての抽象メソッドと抽象プロパティがオーバーライドされるまで、インスタンス化できません。 抽象メソッドは、通常の super 呼び出しの仕組みで呼び出せます。 @abstractmethod は、プロパティやデスクリプタの抽象メソッドを宣言するためにも使えます。

クラスへの抽象メソッドの動的な追加や、作成済みのメソッドやクラスが抽象であるかどうかの変更は、update_abstractmethods() 関数を使う場合にのみサポートされます。 @abstractmethod が影響するのは、通常の継承によるサブクラスだけです。 ABC の register() メソッドで登録された「仮想的サブクラス」には影響しません。

@abstractmethod を他のメソッドデスクリプタと組み合わせる場合は、次の例のように最も内側のデコレータとして適用してください。

class C(ABC):
    @abstractmethod
    def my_abstract_method(self, arg1):
        ...
    @classmethod
    @abstractmethod
    def my_abstract_classmethod(cls, arg2):
        ...
    @staticmethod
    @abstractmethod
    def my_abstract_staticmethod(arg3):
        ...

    @property
    @abstractmethod
    def my_abstract_property(self):
        ...
    @my_abstract_property.setter
    @abstractmethod
    def my_abstract_property(self, val):
        ...

    @abstractmethod
    def _get_x(self):
        ...
    @abstractmethod
    def _set_x(self, val):
        ...
    x = property(_get_x, _set_x)

抽象基底クラスの仕組みと正しく連携するには、デスクリプタが抽象であることを __isabstractmethod__ で示す必要があります。 一般に、デスクリプタを構成するメソッドのいずれかが抽象なら、この属性を True にするべきです。 例えば、Python の組み込み @property は次と同等の処理を行います。

class Descriptor:
    ...
    @property
    def __isabstractmethod__(self):
        return any(getattr(f, '__isabstractmethod__', False) for
                   f in (self._fget, self._fset, self._fdel))

注釈

Java の抽象メソッドと違い、これらの抽象メソッドは実装を持ち得ます。この実装は super() メカニズムを通してそれをオーバーライドしたクラスから呼び出すことができます。これは協調的多重継承を使ったフレームワークにおいて super 呼び出しの終点として有効です。

abc モジュールは、次の古いデコレータもサポートしています。

@abc.abstractclassmethod

Added in version 3.2.

バージョン 3.3 で非推奨: @classmethod と @abstractmethod を組み合わせて使えるようになったため、このデコレータは不要になりました。

抽象クラスメソッドを表す、組み込みの classmethod のサブクラスです。 それ以外の点では @abstractmethod と同様です。

抽象メソッドに @classmethod デコレータを適用すれば、抽象であると正しく認識されるようになったため、この特別なデコレータは非推奨です。

class C(ABC):
    @classmethod
    @abstractmethod
    def my_abstract_classmethod(cls, arg):
        ...
@abc.abstractstaticmethod

Added in version 3.2.

バージョン 3.3 で非推奨: @staticmethod と @abstractmethod を組み合わせて使えるようになったため、このデコレータは不要になりました。

抽象静的メソッドを表す、組み込みの staticmethod のサブクラスです。 それ以外の点では @abstractmethod と同様です。

抽象メソッドに @staticmethod デコレータを適用すれば、抽象であると正しく認識されるようになったため、この特別なデコレータは非推奨です。

class C(ABC):
    @staticmethod
    @abstractmethod
    def my_abstract_staticmethod(arg):
        ...
@abc.abstractproperty

バージョン 3.3 で非推奨: @property、@property.getter、@property.setter、@property.deleter を @abstractmethod と組み合わせて使えるようになったため、このデコレータは不要になりました。

抽象プロパティを表す、組み込みの property のサブクラスです。

抽象メソッドに @property デコレータを適用すれば、抽象であると正しく認識されるようになったため、この特別なデコレータは非推奨です。

class C(ABC):
    @property
    @abstractmethod
    def my_abstract_property(self):
        ...

この例は読み出し専用のプロパティを定義しています。プロパティを構成するメソッドの1つ以上を abstract にすることで、読み書きできる抽象プロパティを定義することができます:

class C(ABC):
    @property
    def x(self):
        ...

    @x.setter
    @abstractmethod
    def x(self, val):
        ...

構成するメソッド全てが abstract でない場合、abstract と定義されたメソッドのみが、具象サブクラスによってオーバーライドする必要があります:

class D(C):
    @C.x.setter
    def x(self, val):
        ...

abc モジュールは、次の関数も提供します。

abc.get_cache_token()

現在の抽象基底クラスのキャッシュトークンを返します。

このトークンは、仮想サブクラスのための抽象基底クラスの現在のバージョンを特定する (等価性検査をサポートしている) 不透明なオブジェクトです。 任意のABCでの ABCMeta.register() の呼び出しごとに、トークンは変更されます。

Added in version 3.4.

abc.update_abstractmethods(cls)

抽象クラスが抽象であるかどうかを再計算する関数です。 クラスを作成した後で、その抽象メソッドを実装したり変更したりした場合に呼び出してください。 通常はクラスデコレータの中から呼び出します。

クラスデコレータとして使えるように、cls を返します。

cls が ABCMeta のインスタンスでなければ、何もしません。

注釈

この関数は、cls のスーパークラスがすでに更新されていることを前提とします。 サブクラスの更新は行いません。

Added in version 3.10.

脚注