【Python】Python ~ 基本編 / 抽象クラス ~

■ はじめに

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