もち256ログ
About Note Log
Log
published: 2021-12-18
pythonのクラスメソッドを異なるファイルで管理する

業務で使用するパッケージなどは、改修の都度に関数が追加されたりするので、コード量が多くなりがちです。

なので「クラスを定義したいけど、クラスメソッドはファイルごとに管理したい」という場合があるのではないでしょうか。

今回は、あるクラスをpythonで定義したうえで、クラスメソッドをファイルごとに管理する方法になります。


実装

パッケージは下記のような配置になります。

myproject内に、クラスが定義されている"some_class.py"、クラスメソッドを定義している"some_pkg1.py"、"some_pkg2.py"を用意します。

myproject
├── some_class.py
├── some_pkg1.py
└── some_pkg2.py

"some_class.py"の内容になります。
インポートしたgetmembers()を使用し、some_pkg1、some_pkg2内に定義されている関数を読み出します。

読み出した関数を、setattr()を使用して、自身の関数と定義させます。

# some_class.py
from inspect import getmembers, isfunction
from . import some_pkg1, some_pkg2

# 関数が定義されたパッケージを記述する
packages = [
  some_pkg1,
  some_pkg2
]

class SomeClass:
  def __init__(self):
    # 他パッケージ内の関数を読み出す
    for package in packages:
      pkg_funcs = getmembers(package, isfunction)
      # 他パッケージの関数を自身のクラスに定義する
      for pkg_func in pkg_funcs:
        setattr(self.__class__, pkg_func[0], pkg_func[1])

あとは、some_pkg1・some_pkg2に任意の関数を定義します。

# some_pkg1.py
def pkg1_func1(self):
    print('call: pkg1_func1')

def pkg1_func2(self):
    print('call: pkg1_func2')
# some_pkg2.py
def pkg2_func1(self):
    print('call: pkg2_func1')

SomeClassをインスタンス化すると、pkg1_func1()など、別モジュールに定義した関数を呼び出すことができます。

>>> from myproject.some_class import SomeClass
>>> sc = SomeClass()

>>> # some_pkg1.pyの関数を実行
>>> sc.pkg1_func1()
call: pkg1_func1

>>> # some_pkg2.pyの関数を実行
>>> sc.pkg2_func1()
call: pkg2_func1

ログ一覧へ戻る