Функция Introspect для определения того, какой аргумент распаковки (позиционный или ключевое слово) был использован
Я искал способ определить, используется ли какой-либо аргумент для распаковки, и я нашел это:
>>> 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 что-то меняет в отношении этой функциональности или ее поведения?
1 ответ
Решение
Как прокомментировал Мигилсон, используйте inspect.getargspec
(более предпочтительно inspect.getfullargspec
в Python 3.x).
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