Дополнительное объяснение:
Я хочу достичь
call(function,(*args,*toomanyargs)) == (function(*args),*toomanyargs)
call(function_with_varargs,(*args))) == (function_with_varargs(*args))
какой питонический способ добиться этого
call примет 1 функцию и 1 кортеж, передаст функции столько аргументов и создаст новый кортеж из результата и аргументов, которые не были переданы функции.






Вы можете узнать, сколько позиционных аргументов принимает функция, обратившись к атрибуту .__code__.co_argcount:
>>> function = lambda a, b, c: a+b+c
>>> function.__code__.co_argcount
3
Однако это не относится к varargs:
>>> function = lambda *a: a
>>> function.__code__.co_argcount
0
Таким образом, более надежным решением является использование inspect.signature:
import inspect
def call(function, args):
# count the positional arguments
params = inspect.signature(function).parameters.values()
if any(param.kind == inspect.Parameter.VAR_POSITIONAL for param in params):
arg_count = len(args)
else:
POSITIONAL_KINDS = {inspect.Parameter.POSITIONAL_ONLY,
inspect.Parameter.POSITIONAL_OR_KEYWORD}
arg_count = sum(1 for param in params if param.kind in POSITIONAL_KINDS)
# take as many arguments as the function accepts
remainder = args[arg_count:]
args = args[:arg_count]
return (function(*args),) + tuple(remainder)
Демо:
>>> function = lambda a, b, c: a+b+c
>>> args = range(5)
>>> call(function, args))
(3, 3, 4)
>>>
>>> function = lambda a, b, c, *d: a+b+c
>>> args = range(5)
>>> call(function, args))
(3,)
Один из способов - использовать locals() (Проверьте количество параметров, переданных в функции Python; https://docs.python.org/3/library/functions.html#locals) и выполнить некоторые математические вычисления в теле каждой функции, чтобы выяснить, сколько аргументов осталось (неиспользуемых). Затем вы можете вернуть результат, который включает в себя кортеж неиспользованных аргументов.
Это работает только с функцией внутри. Это не позволяет вам проверять количество параметров извне.
О, теперь я понимаю, о чем ты говоришь. Я предполагаю, что моим (уточненным) предложением было бы написать функции, которые вы передаете call(), чтобы просто взять все аргументы * и обработать их соответствующим образом.
Потому что функция call хочет узнать, сколько аргументов принимает function.
Вы передаете функцию в качестве аргумента?