やりたいこと
例えばこんなクラス
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')
1・23
なんと2が削除できていません。というのもinspect.getmembers
で取得できるリストはメンバーの名前でソートされているため、上記例ではRemoveChrs
→ RemoveWhiteSpace
→ ToHalfwidth
の順で実行されてしまうのです。
上から順に実行したい場合にはこうします。
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)
1・2 3
>>> StrProcesser.RemoveWhiteSpace(target)
1・23
>>> StrProcesser.RemoveChrs(target, '2')
1・ 3
>>>
>>> StrProcesser.All(target, '2')
1・3
できました!