■ はじめに
https://dk521123.hatenablog.com/entry/2019/10/12/075251
https://dk521123.hatenablog.com/entry/2019/08/29/220537
の続き。 今更ながら、Pythonの抽象クラス(Abstract Class) を知ったので、メモ。
目次
【1】Pythonの抽象クラス - ABC (Abstract Base Classes) 【2】abc.ABC と abc.ABCMeta との違い 【3】使用上の注意 1)abstractclassmethodは非推奨 【4】サンプル 1)Hello world 2)メソッドの引数に渡す 3)応用編:メッセージ管理するクラス
【1】Pythonの抽象クラス - ABC (Abstract Base Classes)
cf. Abstract Base Class = 抽象基底クラス
https://docs.python.org/ja/3/library/abc.html#abc.ABC
* ABC クラスを継承して実装する => はじめ見た時に、テストで適当に作ったクラスかと思ってしまった、、、 => Python には、 interface がないので、その代わりにもなる (以下のサイトなどを参照)
https://www.lifewithpython.com/2017/11/python-interface.html
https://qiita.com/baikichiz/items/7c3fdb721bb72644f638
【2】abc.ABC と abc.ABCMeta との違い
https://docs.python.org/ja/3/whatsnew/3.4.html#abc
より抜粋 ~~~~~~~~~~~~~~~~~ 新規クラス ABC はそのメタクラスとして ABCMeta を持ちます。 この ABC を基底クラスとして使うことは metaclass=abc.ABCMeta を指定するのと本質的に同じ効果を持ちますが、 少ないタイプ数で単純に書ける上に読みやすいものになります。 ~~~~~~~~~~~~~~~~~
要するに
* 書き方が違うだけでほとんど一緒。
【3】使用上の注意
1)abstractclassmethodは非推奨
from abc import ABC, abstractclassmethod class DemoAbstract(ABC): # ★この部分 @abstractclassmethod def initialize(self) -> bool: pass
【4】サンプル
1)Hello world
import abc class SampleAbstract(metaclass=abc.ABCMeta): @abc.abstractmethod def initialize(self) -> bool: pass class SampleExecutor(SampleAbstract): def initialize(self) -> bool: print("Hello world. This is from initialize.") return True # 呼び出し executor = SampleExecutor() executor.initialize() # Hello world. This is from initialize.
2)メソッドの引数に渡す
import abc class BaseDemo(metaclass=abc.ABCMeta): @abc.abstractmethod def get_message(self, msg_params) -> str: pass class Target(BaseDemo): def get_message(self, msg_params) -> str: return "Hello world. {0}".format(msg_params) def print_hello_world(target_class: BaseDemo, msg_params): print(target_class. get_message(msg_params)) # 呼び出し target = Target() print_hello_world(target, "This is args...") # Hello world. This is args...
3)応用編:メッセージ管理するクラス
import abc class MessageBase(metaclass=abc.ABCMeta): def __init__(self, message_id: int, message_format: str): self.message_id = message_id self.message_format = message_format @abc.abstractmethod def get_message(self, message_params) -> str: pass class Message(MessageBase): def get_message(self, message_params) -> str: return f"{str(self.message_id).zfill(5)} - {self.message_format.format(message_params)}" class MessageProvider(object): NOT_FOUND = Message(1, "Not found... {0}.") # 呼び出し target = MessageProvider.NOT_FOUND print(target.get_message("This is just test...")) # 00001 - Not found... This is just test....
参考文献
https://qiita.com/TrashBoxx/items/7a76e46122191529c526
https://ohke.hateblo.jp/entry/2020/02/01/123000
https://qiita.com/kaneshin/items/269bc5f156d86f8a91c4
関連記事
Python ~ 基本編 / 文字列 ~
https://dk521123.hatenablog.com/entry/2019/10/12/075251
Python ~ 基本編 / クラス・継承 ~
https://dk521123.hatenablog.com/entry/2019/08/29/220537
Python ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2014/08/07/231242
「Class properties are deprecated in Python 3.11 ...」対応方法
https://dk521123.hatenablog.com/entry/2025/01/28/235933