29.7. abc --- 抽象基底クラス¶
ソースコード: Lib/abc.py
このモジュールは Python に PEP 3119 で概要が示された 抽象基底クラス (ABC) を定義する基盤を提供します。なぜこれが Python に付け加えられたかについてはその PEP を参照してください。 (ABC に基づいた数の型階層を扱った PEP 3141 と numbers モジュールも参照してください。)
The collections module has some concrete classes that derive from
ABCs; these can, of course, be further derived. In addition the
collections.abc submodule has some ABCs that can be used to test whether
a class or instance provides a particular interface, for example, is it
hashable or a mapping.
This module provides the following classes:
- 
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 ABCMeta class MyABC(metaclass=ABCMeta): pass MyABC.register(tuple) assert issubclass(tuple, MyABC) assert isinstance((), MyABC) - バージョン 3.3 で変更: クラスデコレータとして使うことができるように、登録されたサブクラスを返します。 - バージョン 3.4 で変更: - register()の呼び出しを検出するために、- get_cache_token()関数を使うことができます。
 - また、次のメソッドを抽象基底クラスの中でオーバーライドできます: - 
__subclasshook__(subclass)¶
- (クラスメソッドとして定義しなければなりません。) - subclass がこの ABC のサブクラスと見なせるかどうかチェックします。これによって ABC のサブクラスと見なしたい全てのクラスについて - register()を呼び出すことなく- issubclassの振る舞いをさらにカスタマイズできます。 (このクラスメソッドは 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(metaclass=ABCMeta): @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__()の意味は、- __iter__()メソッドがクラスの(または- __mro__でアクセスされる基底クラスの一つの)- __dict__にある場合にもそのクラスが- MyIterableだと見なされるということです。- 最後に、一番下の行は - Fooを- __iter__()メソッドを定義しないにもかかわらず- MyIterableの仮想的サブクラスにします(- Fooは古い様式の- __len__()と- __getitem__()を用いたイテレータプロトコルを使っています。)。これによって- Fooのメソッドとして- get_iteratorが手に入るわけではないことに注意してください。それは別に提供されています。
- 
- 
class abc.ABC¶
- A helper class that has - ABCMetaas its metaclass. With this class, an abstract base class can be created by simply deriving from- ABC, avoiding sometimes confusing metaclass usage.- Note that the type of - ABCis still- ABCMeta, therefore inheriting from- ABCrequires the usual precautions regarding metaclass usage, as multiple inheritance may lead to metaclass conflicts.- バージョン 3.4 で追加. 
The abc module also provides the following decorators:
- 
@abc.abstractmethod¶
- 抽象メソッドを示すデコレータです。 - このデコレータを使うには、クラスのメタクラスが - ABCMetaかそれを継承したものである必要があります。- ABCMetaの派生クラスをメタクラスに持つクラスは、全ての抽象メソッドとプロパティをオーバーロードしない限りインスタンス化することができません。抽象メソッドは通常の 'super' 呼び出し方法で呼ぶことができます。- abstractmethod()はプロパティやデスクリプタのために抽象メソッドを定義することもできます。- クラスに動的に抽象メソッドを追加する、あるいはメソッドやクラスが作られた後から抽象的かどうかの状態を変更しようと試みることは、サポートされません。 - abstractmethod()が影響を与えるのは正規の継承により派生したサブクラスのみで、ABC の- register()メソッドで登録された "仮想的サブクラス" は影響されません。- abstractmethod()が他のメソッドデスクリプタと組み合わされる場合、次の例のように、一番内側のデコレータとして適用しなければなりません:- class C(metaclass=ABCMeta): @abstractmethod def my_abstract_method(self, ...): ... @classmethod @abstractmethod def my_abstract_classmethod(cls, ...): ... @staticmethod @abstractmethod def my_abstract_staticmethod(...): ... @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- Trueif 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.abstractclassmethod¶
- 組み込みの - classmethod()のサブクラスで、抽象クラスメソッドであることを示します。それ以外は- abstractmethod()と同じです。- この特殊ケースは - classmethod()デコレータが抽象メソッドに適用された場合に抽象的だと正しく認識されるようになったため撤廃されます:- class C(metaclass=ABCMeta): @classmethod @abstractmethod def my_abstract_classmethod(cls, ...): ... - バージョン 3.2 で追加. - バージョン 3.3 で非推奨: - classmethodを- abstractmethod()と一緒に使えるようになったため、このデコレータは冗長になりました。
- 
@abc.abstractstaticmethod¶
- 組み込みの - staticmethod()のサブクラスで、抽象静的メソッドであることを示します。それ以外は- abstractmethod()と同じです。- この特殊ケースは - staticmethod()デコレータが抽象メソッドに適用された場合に抽象的だと正しく認識されるようになったため撤廃されます:- class C(metaclass=ABCMeta): @staticmethod @abstractmethod def my_abstract_staticmethod(...): ... - バージョン 3.2 で追加. - バージョン 3.3 で非推奨: - staticmethodを- abstractmethod()と一緒に使えるようになったため、このデコレータは冗長になりました。
- 
@abc.abstractproperty(fget=None, fset=None, fdel=None, doc=None)¶
- 組み込みの - property()のサブクラスで、抽象プロパティであることを示します。- Using this function requires that the class's metaclass is - ABCMetaor is derived from it. A class that has a metaclass derived from- ABCMetacannot be instantiated unless all of its abstract methods and properties are overridden. The abstract properties can be called using any of the normal 'super' call mechanisms.- この特殊ケースは - property()デコレータが抽象メソッドに適用された場合に抽象的だと正しく認識されるようになったため撤廃されます:- class C(metaclass=ABCMeta): @property @abstractmethod def my_abstract_property(self): ... - この例は読み出し専用のプロパティを定義しています。プロパティを構成するメソッドの1つ以上を abstract にすることで、読み書きできる抽象プロパティを定義することができます: - class C(metaclass=ABCMeta): @property def x(self): ... @x.setter @abstractmethod def x(self, val): ... - 構成するメソッド全てが abstract でない場合、abstract と定義されたメソッドのみが、具象サブクラスによってオーバーライドする必要があります: - class D(C): @C.x.setter def x(self, val): ... - バージョン 3.3 で非推奨: - property、- property.getter()、- property.setter()および- property.deleter()を- abstractmethod()と一緒に使えるようになったため、このデコレータは冗長になりました。
abc モジュールは以下の関数も提供しています:
- 
abc.get_cache_token()¶
- 現在の抽象基底クラスのキャッシュトークンを返します。 - このトークンは、仮想サブクラスのための抽象基底クラスの現在のバージョンを特定する (等価性検査をサポートしている) 不透明なオブジェクトです。 任意のABCでの - ABCMeta.register()の呼び出しごとに、トークンは変更されます。- バージョン 3.4 で追加. 
脚注
| [1] | C++ プログラマは Python の仮想的基底クラスの概念は C++ のものと同じではないということを銘記すべきです。 | 
