2017-03-04 10 views
2

Pythonでは、古いものから新しい関数を作成するメソッドが必要です。Pythonで** kwargsの関数から* argsを取得する関数

入力:引数とデフォルト値としてタプルからペアを持つ新しい機能:キーワード

出力の辞書をとるペアのタプルとともにf(**kwargs)のような機能。私がこれまで持って何

def f(**kwargs): 
    return 'test',kwargs['a'], kwargs['b'] 

def magic(f,argtuple): 
    arglist=",".join([str(ke)+" = "+str(va) for ke,va in argtuple]) 
    keylist=",".join([str(ke)+" = "+str(ke) for ke,va in argtuple]) 
    exec("def g("+arglist+"): return f("+keylist+")") 
    return g 

それは私が欲しいものを行います。

In [25]: f(b=4,a=3) 
Out[25]: ('test', 3, 4) 

In [26]: g=magic(f,(['a',1],['b',2])) 

In [27]: g() 
Out[27]: ('test', 1, 2) 

In [28]: g(a=3,b=5) 
Out[28]: ('test', 3, 5) 

In [29]: import inspect 

In [30]: print inspect.getargspec(f) 
ArgSpec(args=[], varargs=None, keywords='kwargs', defaults=None) 

In [31]: print inspect.getargspec(g) 
ArgSpec(args=['a', 'b'], varargs=None, keywords=None, defaults=(1, 2)) 

私は、文字列を構築したくないとexec機能を使用したくないしかし、 。これを達成する他の方法は何ですか?

+0

'g'は絶対にその署名を持っていなければなりませんか、' * args'と '** kwargs'を受け入れるとうまくいくのでしょうか? –

+0

@Rawing:説明したような署名を持っています。 –

答えて

2

これは、正しい署名を構成するソリューションです。最近ではinspectモジュールへの追加や__signature__特殊属性の追加が最近行われているため、合理的に最新のPythonが必要です。

import inspect 

def build_sig(arg_tuple): 
    return inspect.Signature(parameters = [inspect.Parameter(
     name=name, kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, 
     default=default) for name, default in arg_tuple]) 

def wrap(f, arg_tuple): 
    sig = build_sig(arg_tuple) 
    def g(*args, **kwds): 
     bound = sig.bind(*args, **kwds) 
     bound.apply_defaults() 
     return f(**bound.arguments) 
    g.__signature__ = sig 
    return g 

def f(*args, **kwds): 
    return(args, kwds) 

g = wrap(f, (['a', 1], ['b', 7])) 

print(inspect.getargspec(g)) 
print(g(3)) 

# ArgSpec(args=['a', 'b'], varargs=None, keywords=None, defaults=(1, 7)) 
# ((), {'a': 3, 'b': 7}) 
3

あなたが探しているものはfunctools.partial()です。

import functools 

def f(**kwargs): 
    return 'test',kwargs['a'], kwargs['b'] 

def magic(f, argtuple): 
    return functools.partial(f, **dict(argtuple)) 

g = magic(f, (['a',1],['b',2])) 
print g() # ('test', 1, 2) 
+0

あなたの解のオブジェクト 'g'は関数ではありません –

+0

ええ、でもそれは呼び出し可能です。 '>>> callable(g) True' アヒルタイピングの原則に従った関数の代わりに使用するのはまったく問題ありません。 – fodma1

+0

これは私が探していたものではありません。たとえば、この呼び出し可能なものでは、タブ補完は機能しません。 –

関連する問題