2017-03-04 104 views
2

在Python中,我想要一個從舊函數構建新函數的方法。從函數中獲取* args函數與python中的kwargs

輸入:用對的元組像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

這裏是一個解決方案,也構建正確的簽名。它需要一個合理的最新的Python,因爲它使用了inspect模塊的相對近期新增功能,也使用了__signature__特殊屬性。

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

這不是我正在尋找的。例如,對於這個可調用的東西,選項卡完成不起作用。 –