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

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

Using this decorator requires that the class's metaclass is ABCMeta or is derived from it. A class that has a metaclass derived from ABCMeta cannot be instantiated unless all of its abstract methods and properties are overridden. The abstract methods can be called using any of the normal 'super' call mechanisms. @abstractmethod may be used to declare abstract methods for properties and descriptors.

Dynamically adding abstract methods to a class, or attempting to modify the abstraction status of a method or class once it is created, are only supported using the update_abstractmethods() function. The @abstractmethod only affects subclasses derived using regular inheritance; "virtual subclasses" registered with the ABC's register() method are not affected.

When @abstractmethod is applied in combination with other method descriptors, it should be applied as the innermost decorator, as shown in the following usage examples:

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)

In order to correctly interoperate with the abstract base class machinery, the descriptor must identify itself as abstract using __isabstractmethod__. In general, this attribute should be True if any of the methods used to compose the descriptor are abstract. For example, Python's built-in @property does the equivalent of:

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 で非推奨: It is now possible to use @classmethod with @abstractmethod, making this decorator redundant.

A subclass of the built-in classmethod, indicating an abstract classmethod. Otherwise it is similar to @abstractmethod.

This special case is deprecated, as the @classmethod decorator is now correctly identified as abstract when applied to an abstract method:

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

Added in version 3.2.

バージョン 3.3 で非推奨: It is now possible to use @staticmethod with @abstractmethod, making this decorator redundant.

A subclass of the built-in staticmethod, indicating an abstract staticmethod. Otherwise it is similar to @abstractmethod.

This special case is deprecated, as the @staticmethod decorator is now correctly identified as abstract when applied to an abstract method:

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

バージョン 3.3 で非推奨: It is now possible to use @property, @property.getter, @property.setter and @property.deleter with @abstractmethod, making this decorator redundant.

A subclass of the built-in property, indicating an abstract property.

This special case is deprecated, as the @property decorator is now correctly identified as abstract when applied to an abstract method:

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.

脚注