28.8。 abc —抽象基本クラス
バージョン2.6の新機能。
ソースコード: :source: `Lib / abc.py`
このモジュールは、 PEP 3119 で概説されているように、Pythonで抽象基本クラス(ABC)を定義するためのインフラストラクチャを提供します。 これがPythonに追加された理由については、PEPを参照してください。 (ABCに基づく数値の型階層については、 PEP 3141 および numbers モジュールも参照してください。)
collections モジュールには、ABCから派生したいくつかの具象クラスがあります。 もちろん、これらはさらに導き出すことができます。 さらに、 collections モジュールにはいくつかのABCがあり、クラスまたはインスタンスが特定のインターフェイスを提供するかどうかをテストできます。たとえば、ハッシュ可能かどうか、マッピングかどうかなどです。
このモジュールは、次のクラスを提供します。
- class abc.ABCMeta
抽象基本クラス(ABC)を定義するためのメタクラス。
このメタクラスを使用してABCを作成します。 ABCは直接サブクラス化でき、ミックスインクラスとして機能します。 関連のない具象クラス(組み込みクラスも含む)と関連のないABCを「仮想サブクラス」として登録することもできます。これらとその子孫は、組み込みの issubclass()関数によって登録ABCのサブクラスと見なされます。ただし、登録ABCはMRO(メソッド解決順序)に表示されず、登録ABCによって定義されたメソッド実装を呼び出すこともできません( super()を介しても)。 1
ABCMeta のメタクラスで作成されたクラスには、次のメソッドがあります。
- register(subclass)
サブクラスをこのABCの「仮想サブクラス」として登録します。 例えば:
from abc import ABCMeta class MyABC: __metaclass__ = ABCMeta MyABC.register(tuple) assert issubclass(tuple, MyABC) assert isinstance((), MyABC)
抽象基本クラスでこのメソッドをオーバーライドすることもできます。
- __subclasshook__(subclass)
(クラスメソッドとして定義する必要があります。)
サブクラスがこのABCのサブクラスと見なされるかどうかを確認します。 これは、ABCのサブクラスを検討するすべてのクラスで register()を呼び出す必要なしに、
issubclass
の動作をさらにカスタマイズできることを意味します。 (このクラスメソッドは、ABCの__subclasscheck__()
メソッドから呼び出されます。)このメソッドは、
True
、False
、またはNotImplemented
を返す必要があります。True
を返す場合、サブクラスはこのABCのサブクラスと見なされます。False
を返す場合、サブクラスは、通常は1つであっても、このABCのサブクラスとは見なされません。NotImplemented
が返される場合、サブクラスチェックは通常のメカニズムで続行されます。
これらの概念のデモンストレーションについては、次のABC定義の例を参照してください。
class Foo(object): 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 __()クラスメソッドは、 __ dict __ (またはその基本クラスの1つに __ iter __()メソッドがあるクラスを示します、 __ mro __ リストからアクセス)も
MyIterable
と見なされます。最後に、最後の行は、 __ iter __()メソッドを定義していなくても
Foo
をMyIterable
の仮想サブクラスにします(古いスタイルの反復可能なプロトコルを使用しますが、__len__()
および__getitem__()
で定義されます)。 これにより、get_iterator
がFoo
のメソッドとして使用可能になるわけではないため、別途提供されることに注意してください。
また、次のデコレータも提供します。
- abc.abstractmethod(function)
抽象メソッドを示すデコレータ。
このデコレータを使用するには、クラスのメタクラスが ABCMeta であるか、それから派生している必要があります。 ABCMeta から派生したメタクラスを持つクラスは、その抽象メソッドとプロパティがすべてオーバーライドされない限り、インスタンス化できません。 抽象メソッドは、通常の「スーパー」呼び出しメカニズムのいずれかを使用して呼び出すことができます。
クラスに抽象メソッドを動的に追加したり、作成されたメソッドまたはクラスの抽象化ステータスを変更しようとしたりすることはサポートされていません。 abstractmethod()は、通常の継承を使用して派生したサブクラスにのみ影響します。 ABCの
register()
メソッドで登録された「仮想サブクラス」は影響を受けません。使用法:
class C: __metaclass__ = ABCMeta @abstractmethod def my_abstract_method(self, ...): ...
ノート
Java抽象メソッドとは異なり、これらの抽象メソッドには実装がある場合があります。 この実装は、それをオーバーライドするクラスから super()メカニズムを介して呼び出すことができます。 これは、協調的な多重継承を使用するフレームワークでのスーパーコールのエンドポイントとして役立つ可能性があります。
- abc.abstractproperty([fget[, fset[, fdel[, doc]]]])
組み込みの property()のサブクラスで、抽象プロパティを示します。
この関数を使用するには、クラスのメタクラスが ABCMeta であるか、それから派生している必要があります。 ABCMeta から派生したメタクラスを持つクラスは、その抽象メソッドとプロパティがすべてオーバーライドされない限り、インスタンス化できません。 抽象プロパティは、通常の「スーパー」呼び出しメカニズムのいずれかを使用して呼び出すことができます。
使用法:
class C: __metaclass__ = ABCMeta @abstractproperty def my_abstract_property(self): ...
これは読み取り専用プロパティを定義します。 'long'形式のプロパティ宣言を使用して、読み取り/書き込み抽象プロパティを定義することもできます。
class C: __metaclass__ = ABCMeta def getx(self): ... def setx(self, value): ... x = abstractproperty(getx, setx)
脚注
- 1
- C ++プログラマーは、Pythonの仮想基本クラスの概念がC ++の概念と同じではないことに注意する必要があります。