python de 同一メゾッド名の型チェック付き呼び分け
バイト中、以下のようなコードを見つけた。
def something1(x,y): print 'something1' def something2(x,y): print 'something2' def something3(x,y,z): print 'something3' def invoke(*args): argc=len(args) exp_message='not match function' if argc==3: something3(args[0],args[1],args[2]) elif argc==2: if isinstance(args[0],int) and isinstance(args[1],str): something2(args[0],args[1]) elif isinstance(args[0],int) and isinstance(args[1],float): something1(args[0],args[1]) else: raise Exception,exp_message else: raise Exception,exp_message invoke("hoge",42,4.2) invoke(42,"hoge") invoke(42,4.2)
うーん。凄まじいハードコードである。やりたい事はオーバーロードだろう。私はpythonの専門家ではないので、更に良い解決法はあるのだろうが、取り敢えず以下のように引数の違いで呼び分ける上で型チェックをするようにした。
import sys exp_message="not match function" class Invoker(object): def __init__(self): self.functions=[] def __call__(self,*args,**kwargs): for function in self.functions: if len(args)==function.func_code.co_argcount: return function(*args) raise Exception,exp_message def invoke_impl(func): hs=sys._getframe(1).f_globals.get(func.__name__) if hs is None: hs=Invoker() hs.functions.append(func) return hs; @invoke_impl def something(x,y,z): if not (isinstance(x,str) and isinstance(y,int) and isinstance(z,float)): raise Exception,exp_message print 'something3' @invoke_impl def something(x,y): if isinstance(x,int) and isinstance(y,str): print 'something2' elif isinstance(x,int) and isinstance(y,float): print 'something1' else: raise Exception,exp_message something("hoge",42,4.2) something(42,"hoge") something(42,4.2)
型チェックはやはりisinstance
を使う他はないだろうか。