众所周知,Python 函数最多可以有 256 个参数。我很想知道这个限制是否适用*args
以及**kwargs
何时以下列方式展开:
items = [1,2,3,4,5,6]
def do_something(*items):
pass
我问是因为,假设可能存在大于 256 个项目的列表被展开为一组*args
or的情况**kwargs
。
众所周知,Python 函数最多可以有 256 个参数。我很想知道这个限制是否适用*args
以及**kwargs
何时以下列方式展开:
items = [1,2,3,4,5,6]
def do_something(*items):
pass
我问是因为,假设可能存在大于 256 个项目的列表被展开为一组*args
or的情况**kwargs
。
WFM
>>> fstr = 'def f(%s): pass' % (', '.join(['arg%d' % i for i in range(5000)]))
>>> exec(fstr)
>>> f
<function f at 0x829bae4>
更新:正如布赖恩所注意到的,限制在调用方:
>>> exec 'f(' + ','.join(str(i) for i in range(5000)) + ')'
Traceback (most recent call last):
File "<pyshell#63>", line 1, in <module>
exec 'f(' + ','.join(str(i) for i in range(5000)) + ')'
File "<string>", line 1
SyntaxError: more than 255 arguments (<string>, line 1)
另一方面,这有效:
>>> f(*range(5000))
>>>
结论:不,它不适用于展开的论点。
在 Python 3.6 及之前版本中,限制是由于编译后的字节码如何处理使用位置参数和/或关键字参数调用函数。
关注的字节码操作是CALL_FUNCTION
它携带一个op_arg
长度为 4 个字节的字节码,但使用了两个最低有效字节。其中,最高有效字节表示堆栈上关键字参数的数量,最低有效字节表示堆栈上位置参数的数量。因此,您最多可以有0xFF == 255
关键字参数或0xFF == 255
位置参数。
此限制不适用于*args
and**kwargs
因为使用该语法的调用使用字节码 ops CALL_FUNCTION_VAR
, CALL_FUNCTION_KW
, 和CALL_FUNCTION_VAR_KW
取决于签名。对于这些操作码,堆栈由一个可迭代的 the和*args
一个dict
. **kwargs
这些项目直接传递给接收器,接收器根据需要展开它们。
在 Python 3.7 和更新版本中,没有限制。这是issue #27213和issue #12844中工作的结果;#27213 重新设计了CALL_FUNCTION*
操作码系列以提高性能和简单性(3.6 的一部分),释放操作码参数以仅对单个参数计数进行编码,并且 #12844 删除了阻止具有更多参数的代码被编译的编译时检查。
所以从 3.7 开始,使用EXTENDED_ARG()
opcode,现在完全没有限制你可以使用显式参数传入多少个参数,保存多少个可以放入堆栈(现在受你的记忆约束):
>>> import sys
>>> sys.version_info
sys.version_info(major=3, minor=7, micro=0, releaselevel='alpha', serial=2)
>>> def f(*args, **kwargs): pass
...
>>> exec("f({})".format(', '.join(map(str, range(256)))))
>>> exec("f({})".format(', '.join(map(str, range(2 ** 16)))))
请注意,列表、元组和字典仅限于sys.maxsize
元素,因此如果被调用的函数使用*args
和/或**kwargs
catch-all 参数,那么这些都是有限的。
对于*args
and调用语法(扩展参数),除了Python 标准类型的相同大小限制外,**kwargs
没有其他限制。sys.maxint
在 Python 3.7 之前的版本中,CPython 在调用中限制为 255 个显式传递的参数:
>>> def f(*args, **kwargs): pass
...
>>> exec("f({})".format(', '.join(map(str, range(256)))))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1
SyntaxError: more than 255 arguments
这个限制是存在的,因为在 Python 3.5 之前,CALL_FUNCTION
操作码重载了操作码参数以对堆栈上的位置参数和关键字参数的数量进行编码,每个参数都以单个字节编码。
这似乎是编译源代码的限制,因此可能只存在于直接传递的参数,而不是 *args 或 **kwargs。
相关代码可以在ast.c中找到:
if (nargs + nkeywords + ngens > 255) {
ast_error(n, "more than 255 arguments");
return NULL;
}
但请注意,这是在 ast_for_call 中,因此仅适用于调用方。即f(a,b,c,d,e...)
,而不是定义,尽管它会同时计算位置参数(a,b,c,d)
和keyword (a=1, b=2, c=3)
样式参数。实际参数*args
和**kwargs
参数看起来应该只算作调用端用于这些目的的一个参数。
对于 **kwargs,如果我没记错的话,这是一本字典。因此,它几乎没有限制。
对于 *args,我不太确定,但我认为它是一个元组或一个列表,所以它也几乎没有限制。
没有限制,我的意思是除了内存限制。
我尝试了一个包含 4000 个项目的列表,并且成功了。所以我猜它也适用于更大的值。