<p>通过访问<code>.__code__.co_argcount</code>属性,可以了解函数接受多少位置参数:</p>
<pre><code>>>> function = lambda a, b, c: a+b+c
>>> function.__code__.co_argcount
3
</code></pre>
<p>但是,这并不尊重varargs:</p>
<pre><code>>>> function = lambda *a: a
>>> function.__code__.co_argcount
0
</code></pre>
<p>所以更可靠的解决方案是使用<a href="https://docs.python.org/3/library/inspect.html#inspect.signature" rel="nofollow noreferrer">^{<cd2>}</a>:</p>
<pre><code>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)
</code></pre>
<p>演示:</p>
<pre><code>>>> 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,)
</code></pre>