Есть ли способ вызвать функцию Python с неправильным количеством аргументов, не вызывая TypeError?
-
06-09-2019 - |
Вопрос
Когда вы вызываете функцию с неправильным количеством аргументов или с аргументом ключевого слова, которого нет в ее определении, вы получаете ошибку TypeError.Мне нужен фрагмент кода, который принимает обратный вызов и вызывает его с переменными аргументами в зависимости от того, что поддерживает обратный вызов.Один из способов сделать это - для обратного вызова cb
, использовать cb.__code__.cb_argcount
и cb.__code__.co_varnames
, но я бы предпочел абстрагировать это во что-то вроде apply
, но это касается только тех аргументов, которые «подходят».
Например:
def foo(x,y,z):
pass
cleanvoke(foo, 1) # should call foo(1, None, None)
cleanvoke(foo, y=2) # should call foo(None, 2, None)
cleanvoke(foo, 1,2,3,4,5) # should call foo(1, 2, 3)
# etc.
Есть ли что-нибудь подобное уже в Python или мне нужно написать это с нуля?
Решение
Вместо того, чтобы копаться в деталях самостоятельно, вы можете осмотреть подпись функции - вы, вероятно, захотите inspect.getargspec(cb)
.
Мне не совсем понятно, как именно вы хотите использовать эту информацию и имеющиеся у вас аргументы для «правильного» вызова функции.Предположим для простоты, что вас интересуют только простые именованные аргументы, а значения, которые вы хотите передать, находятся в формате dict. d
...
args = inspect.getargspec(cb)[0]
cb( **dict((a,d.get(a)) for a in args) )
Может быть, вы хотите чего-то более изысканного и можете уточнить, что именно?
Другие советы
Это может быть?
def fnVariableArgLength(*args, **kwargs):
"""
- args is a list of non keywords arguments
- kwargs is a dict of keywords arguments (keyword, arg) pairs
"""
print args, kwargs
fnVariableArgLength() # () {}
fnVariableArgLength(1, 2, 3) # (1, 2, 3) {}
fnVariableArgLength(foo='bar') # () {'foo': 'bar'}
fnVariableArgLength(1, 2, 3, foo='bar') # (1, 2, 3) {'foo': 'bar'}
Редактировать Ваши варианты использования
def foo(*args,*kw):
x= kw.get('x',None if len(args) < 1 else args[0])
y= kw.get('y',None if len(args) < 2 else args[1])
z= kw.get('z',None if len(args) < 3 else args[2])
# the rest of foo
foo(1) # should call foo(1, None, None)
foo(y=2) # should call foo(None, 2, None)
foo(1,2,3,4,5) # should call foo(1, 2, 3)