2014-01-10 39 views
2

我正在尋找一種方法來找出一些論據是否用於拆包,我發現這一點:反思功能,以確定哪些參數拆包(位置或關鍵字)用於

>>> def func_has_positional_args(func): 
    std_args = func.func_code.co_argcount 
    wildcard_args = len(func.func_code.co_varnames) - std_args 
    if wildcard_args == 2: 
     return True # yes, has both positional and keyword args 
    elif wildcard_args == 0: 
     return False # has neither positional, nor keyword args 
    else: 
     raise NotImplementedError('Unable to tell') 


>>> func_has_keyword_args = func_has_positional_args 
>>> def test1(a, b, *args, **kwargs): pass 

>>> func_has_positional_args(test1), func_has_keyword_args(test1) 
(True, True) 
>>> def test2(a, b): pass 

>>> func_has_positional_args(test2), func_has_keyword_args(test2) 
(False, False) 
>>> def test3(a, b, *args): pass 

>>> func_has_positional_args(test3) 

Traceback (most recent call last): 
    File "<pyshell#52>", line 1, in <module> 
    func_has_positional_args(test3) 
    File "<pyshell#41>", line 9, in func_has_positional_args 
    raise NotImplementedError('Unable to tell') 
NotImplementedError: Unable to tell 

所以我能告訴,如果沒有位置,也沒有關鍵字參數解包。我也能夠判斷兩者是否都有,但是如果只有一個「通配符」,我無法區分使用了哪種「通配符」類型的參數。

你能幫我實現以下結果嗎?

# Already satisfied with above code: 
assert func_has_positional_args(test1) == True 
assert func_has_keyword_args(test1) == True 
assert func_has_positional_args(test2) == False 
assert func_has_keyword_args(test2) == False 

# Missing functionality (tests are failing): 
assert func_has_positional_args(test3) == True 
assert func_has_keyword_args(test3) == False 

此外,Python 3是否改變任何關於此功能或其行爲?

+3

...我不知道我真的密切關注這一點,但你不找'inspect.getargspec'?你在做什麼不同? – mgilson

+0

@mgilson:是的,bullseye;)看起來我太專注於查找函數屬性,而不是查看'inspect'模塊......您是否願意將它作爲答案發布? – Tadeck

回答

3

As mgilson評論說,使用inspect.getargspec(在Python 3.x中更優選爲inspect.getfullargspec)。

import inspect 

def func_has_positional_args(func): 
    spec = inspect.getfullargspec(func) 
    return bool(spec.varargs) # varargs: name of the * argument or None 
def func_has_keyword_args(func): 
    spec = inspect.getfullargspec(func) 
    return bool(spec.varkw) # varkw: name of the ** argument or None 

例子:

>>> def test1(a, b, *args, **kwargs): pass 
... 
>>> def test2(a, b): pass 
... 
>>> def test3(a, b, *args): pass 
... 
>>> func_has_positional_args(test1) 
True 
>>> func_has_keyword_args(test1) 
True 
>>> func_has_positional_args(test2) 
False 
>>> func_has_keyword_args(test2) 
False 
>>> func_has_positional_args(test3) 
True 
>>> func_has_keyword_args(test3) 
False 
+0

謝謝,編寫Python 2.x + 3.x兼容代碼的首選方式是在導入'inspect'時實際執行此操作,對吧?我沒有找到這個功能的「六」模塊支持。 – Tadeck

+0

@Tadeck,如果您想要在Python 2和3中運行的代碼,請使用'inspect.getargspec'。 (用'關鍵字'替換'varkw')。 – falsetru

+0

@Tadeck,'inspect.getargspec'已根據文檔棄用。但即使在[Python 3.4]中,getargspec仍然存在(http://docs.python.org/3.4/library/inspect.html#inspect.getargspec)。 – falsetru

相關問題