5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Python】inspectでクラスのメソッドを全部使う

Last updated at Posted at 2019-06-18

やりたいこと

例えばこんなクラス

import re
import zenhan

class StrProcesser:
    @staticmethod
    def ToHalfwidth(str_) -> str:
        return zenhan.z2h(str_, 3).replace('', '')

    @staticmethod
    def RemoveWhiteSpace(str_) -> str:
        return ''.join(str_.split())

    @staticmethod
    def RemoveChrs(str_, remove='') -> str:
        pattern = f'[{re.escape(remove)}]'
        return re.sub(pattern, '', str_)

それぞれの機能は個々でも使いたいけど、全部まとめて使えたら便利だな~っていうのを実現するために
標準ライブラリのinspectを使っていきます。

追加するコード

import inspect

class StrProcesser:

    ...

    @classmethod
    def All(cls, str_, remove='') -> str:
        for _, func in inspect.getmembers(cls, inspect.isfunction):
            local_vars = locals()
            passing_args = {p: local_vars[p] for p in inspect.signature(func).parameters}
            str_ = func(**passing_args)
        return str_

inspect.getmembersの第2引数にinspect.isfunctionを渡すことによって、第1引数に渡したオブジェクトの中から自分(All)以外の関数名と関数のタプルを抜くことができます。
inspect.signature(func).parametersはParameterオブジェクトですが、forで回すと引数名(str)が取得できます。
あとは多分見ればわかると思うので割愛。

やってみる

しかし…

>>> target = '1・2 3'
>>> StrProcesser.All(target, '2')

123

なんと2が削除できていません。というのもinspect.getmembersで取得できるリストはメンバーの名前でソートされているため、上記例ではRemoveChrsRemoveWhiteSpaceToHalfwidthの順で実行されてしまうのです。

上から順に実行したい場合にはこうします。

import inspect
import re
import zenhan


class StrProcesser:
    names = locals().keys()

    @staticmethod
    def ToHalfwidth(str_) -> str:
        return zenhan.z2h(str_, 3).replace('', '')

    @staticmethod
    def RemoveWhiteSpace(str_) -> str:
        return ''.join(str_.split())

    @staticmethod
    def RemoveChrs(str_, remove='') -> str:
        pattern = f'[{re.escape(remove)}]'
        return re.sub(pattern, '', str_)

    @classmethod
    def All(cls, str_, remove='') -> str:
        functions = dict(inspect.getmembers(cls, inspect.isfunction))
        valid_order_func_names = filter(lambda key: key in functions, cls.names)
        for func_name in valid_order_func_names:
            local_vars = locals()
            func_params = inspect.signature(functions[func_name]).parameters
            passing_args = {p: local_vars[p] for p in func_params}
            str_ = functions[func_name](**passing_args)
        return str_

辞書の順序が保証されているのはPython3.7からなので、それ以前のバージョンだとうまくいかないかもしれません。

最終結果

>>> target = '1・2 3'
>>> 
>>> StrProcesser.ToHalfwidth(target)
12 3
>>> StrProcesser.RemoveWhiteSpace(target)
1・23
>>> StrProcesser.RemoveChrs(target, '')
1・ 3
>>> 
>>> StrProcesser.All(target, '2')
13

できました!

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?