2009-06-01 6 views
1

引数が間違っている関数を呼び出すか、キーワード引数が定義にない関数を呼び出すと、TypeErrorが返されます。私は、コールバックをサポートするために、コールバックを受け取り、可変引数で呼び出すコードを欲しいと思います。コールバックcbの場合は、cb.__code__.cb_argcountcb.__code__.co_varnamesを使用しますが、私はむしろそれをapplyのようなものに抽象化しますが、それは "適合"する引数を適用するだけです。例えばTypeErrorを呼び出さずに、引数の数が違うPython関数を呼び出す方法はありますか?

def foo(x,y,z): 
    pass 

cleanvoke(foo, 1)   # should call foo(1, None, None) 
cleanvoke(foo, y=2)  # should call foo(None, 2, None) 
cleanvoke(foo, 1,2,3,4,5) # should call foo(1, 2, 3) 
          # etc. 

は、すでにPythonで、このようなものはありますか、それは私が一から書くべきものでしょうか?

答えて

7

自分で詳細を掘り下げるのではなく、inspect関数の署名 - inspect.getargspec(cb)が必要です。

関数を「正しく」呼び出すために、その情報とargsをどのように使いたいかは完全にわかりません。

args = inspect.getargspec(cb)[0] 
cb(**dict((a,d.get(a)) for a in args)) 

はたぶん、あなたは手の込んだ何かをしたい、と正確に何で手の込んだことができます...あなただけの単純な名前の引数を気に、そしてあなたが合格したい値はdictのdであると仮定すると、簡単にするために?

+0

getargspecは(__magic__ものに目を通す必要はありません、 例えば)。 私はあなたが提案したように( "a"の代わりに "k"を付けずに)argsという名前のフィルタリングを行いたいと思っています)、長さで通常の引数 - 呼び出しに十分な引数がない場合はNoneを書き、議論 たぶん私はデコレータにしてもいいでしょう:) –

+0

2番目の考えでは、私は非常に明確にしていないことが正しいです(自分の頭でも)。コールバックには、デフォルト、* args、** kwargsの異なる組み合わせがあります。 –

+0

ありがとう、typoを修正しました。それについてもっと考えると、私は名前付き引数に焦点を当てることは良いアイデアだと信じています - ポジションと名前を混在させることは常に難しいです。私のコードの重要な機能強化の1つは、引数aがデフォルト値を持っていて、dにない場合、自分のコードが(.getによって)実行されるのではなく、強制的にNoneにすることです。 –

3

これは多分ですか?間違いなく、この私を心配された方法で、より多くの「きれい」になります

def fnVariableArgLength(*args, **kwargs): 
    """ 
    - args is a list of non keywords arguments 
    - kwargs is a dict of keywords arguments (keyword, arg) pairs 
    """ 
    print args, kwargs 


fnVariableArgLength() #() {} 
fnVariableArgLength(1, 2, 3) # (1, 2, 3) {} 
fnVariableArgLength(foo='bar') #() {'foo': 'bar'} 
fnVariableArgLength(1, 2, 3, foo='bar') # (1, 2, 3) {'foo': 'bar'} 

編集あなたのユースケース

def foo(*args,*kw): 
    x= kw.get('x',None if len(args) < 1 else args[0]) 
    y= kw.get('y',None if len(args) < 2 else args[1]) 
    z= kw.get('z',None if len(args) < 3 else args[2]) 
    # the rest of foo 

foo(1)   # should call foo(1, None, None) 
foo(y=2)  # should call foo(None, 2, None) 
foo(1,2,3,4,5) # should call foo(1, 2, 3) 
+0

ナー、申し訳ありませんが十分に明確ではない - 私は何を意味するか説明するためにいくつかの例を追加しました。 –

関連する問題