2016-02-19 68 views
1

我想複製一個函數的簽名來定義一個擴展它的新函數。 Python 3.4,如果版本問題的解決方案。如何複製python函數的簽名並定義一個新函數?

ham.py

def spam(pork *, salt, taste=False): 
    """External function I don't control.""" 
    return food 

eggs.py

import ham 

def breakfast(pork, *, drama, salt, taste=False): 
    """The function I want to define, done statically.""" 
    return eggs, ham.spam(pork=pork, salt=salt, taste=taste) 

我想定義breakfast因此,如果用戶安裝了一個不同,但兼容的版本的ham.pybreakfast功能將包括對ham.spam中參數的任何更改。

例:

# Probably not how you do this... 
signature = inspect.Signature(breakfast) 
breakfast = types.FunctionType(
    how-do-i-make-a-multi-line-code-object, 
    what-do-i-use-for-globals, 
    name='breakfast', 
    argdefs=from-signature) 
+0

「早餐」是否對其論點採取任何行動,而不是將它們直接傳遞給「垃圾郵件」? – jwodder

+0

@jwodder否,參數直接傳遞。 – ToBeReplaced

回答

0

要回答你的問題的部分,讓你可以使用inspect.getargspecinspect.getfullargspecinspect模塊簽名

import inspect 
fullArgSpec = inspect.getfullargspec(spam) 

這將返回

FullArgSpec (args = ['pork','salt','taste'],varargs = None,varkw = None,defaults =( False),kwonlyargs = [],kwonlydefaults = None,annotations = {})

用這個,你可以建立參數調用的字符串。首先建立postional參數,然後建立關鍵字參數。粗略地說,像這樣的東西

argumentsString = "" 
for argument in itertools.chain(fullArgSpec.args, fullArgSpec.kwonlyargs): 
    if argument in locals(): 
     argumentsString += '{}={},'.format(argument,locals()[argument]) 

請注意,如果任何位置參數丟失,這可能會失敗。如果需要的話,你應該添加一個支票在這個時候cleanlly退出。

第二部分,你想建立功能的地方,我希望能找到像apply這樣的東西,但似乎不推薦使用。之所以構建argumentString是使用exec執行呼叫使用內置參數字符串匹配一個正常的函數調用來執行這spam

exec('spam({})'.format(argumentsString)) 

傳遞給exec的字符串是

垃圾郵件(豬肉= 2,鹽= 3)