Pythonの抽象基底クラス (Abstract Base Class, ABC)
Pythonでは抽象基底クラス (Abstract Base Class, ABC)を実装することができます。
Python3でも3.4からの機能です。
抽象基底クラスの導入については、PEPの日本語訳をしてくれている人がいます。
こちら→ http://mft.la.coocan.jp/script/python/pep-3119.html
Pythonのドキュメントの抽象基底クラスの説明はこちら→ https://docs.python.jp/3/library/abc.html
「ABCs VS ダックタイピング」という箇所には、
ABC は Python 2 に良い解決策が無かった、たとえばマッピングとシーケンスを見分けるといった問題を解決したいというものとあります。
ABCを使ってみる
1 2 3 4 5 6 7 8 9 10 |
from abc import ABCMeta, abstractmethod # まずはインポート class A(metaclass=ABCMeta): # 抽象基底クラスAを実装 @abstractmethod # 子クラスではfoo()の実装を必須とする def foo(self): pass A() # 抽象クラスは実行できない |
$ python abc.py
Traceback (most recent call last):
File "abc.py", line 10, in
A()
TypeError: Can't instantiate abstract class A with abstract methods foo
File "abc.py", line 10, in
A()
TypeError: Can't instantiate abstract class A with abstract methods foo
抽象クラスのAはインタンス化できませんよとエラーが発生します。
@abstractmethodは抽象メソッドを示すデコレータです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from abc import ABCMeta, abstractmethod class A(metaclass=ABCMeta): @abstractmethod def foo(self): pass class B(A): # foo()を実装していないからダメ pass B() |
Traceback (most recent call last):
File "abc.py", line 14, in
B()
TypeError: Can't instantiate abstract class B with abstract methods foo
File "abc.py", line 14, in
B()
TypeError: Can't instantiate abstract class B with abstract methods foo
foo()を実装していないクラスBはインスタンス化できないよとエラーが発生します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
from abc import ABCMeta, abstractmethod class A(metaclass=ABCMeta): @abstractmethod def foo(self): pass class B(A): pass class C(A): def foo(self): # ちゃんとabstractメソッドを実装しています print('Python Carnival') C() # うまく動きます C().foo() # Cクラスのfoo()を実行します |
$ python abc.py
Python Carnival
Python Carnival
registerメソッドで仮想的サブクラスを登録できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
from abc import ABCMeta, abstractmethod class A(metaclass=ABCMeta): @abstractmethod def foo(self): pass class B(): def foo(self): # 仮想的サブクラスでもfoo()の実装は必須 print('Python3 ABC') class C(A): def foo(self): print('Python Carnival') A.register(B) # 抽象クラスAにクラスBを登録 B().foo() |
$ python abc.py
Python3 ABC
Python3 ABC