【问题标题】:What is a maximum number of arguments in a Python function?Python 函数中的最大参数数是多少?
【发布时间】:2010-10-17 09:37:10
【问题描述】:

众所周知,Python 函数最多可以有 256 个参数。我很想知道当*args**kwargs 以下列方式展开时,此限制是否适用:

items = [1,2,3,4,5,6]

def do_something(*items):
    pass

我问是因为,假设在某些情况下,超过 256 个项目的列表会被展开为一组 *args**kwargs

【问题讨论】:

    标签: python function arguments language-features limit


    【解决方案1】:

    WFM

    >>> fstr = 'def f(%s): pass' % (', '.join(['arg%d' % i for i in range(5000)]))
    >>> exec(fstr)
    >>> f
    <function f at 0x829bae4>
    

    更新:正如 Brian 注意到的那样,限制在调用方:

    >>> 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))
    >>> 
    

    结论:不,它不适用于展开的参数。

    【讨论】:

    • 看起来限制在调用方。试试 exec 'f(' + ','.join(str(i) for i in range(5000)) + ')'
    • @Stefan: 为我工作
    • 这个答案已经过时了。 Python 3.7 中删除了 255 arg 限制
    【解决方案2】:

    在 Python 3.6 及之前版本中,限制是由于编译后的字节码如何处理使用位置参数和/或关键字参数调用函数。

    关注的字节码操作是CALL_FUNCTION,它带有一个长度为4字节的op_arg,但使用了两个最低有效字节。其中,最高有效字节表示堆栈上关键字参数的数量,最低有效字节表示堆栈上位置参数的数量。因此,您最多可以有0xFF == 255 关键字参数或0xFF == 255 位置参数。

    此限制不适用于 *args**kwargs,因为使用该语法的调用使用字节码操作 @​​987654322@、CALL_FUNCTION_KWCALL_FUNCTION_VAR_KW,具体取决于签名。对于这些操作码,堆栈由*args 的可迭代对象和**kwargsdict 组成。这些项目直接传递给接收器,接收器根据需要展开它们。

    【讨论】:

    • 这是 CPython 的实现限制,还是 Python 本身的一部分?
    • 这是一个 CPython 字节码的实现细节。
    • ……确实如此。该限制将在 CPython 3.7 中解除。
    【解决方案3】:

    在 Python 3.7 及更高版本中,没有限制。这是issue #27213issue #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 包罗万象的参数,那么这些 受限的。

    对于 *args**kwargs 调用语法(扩展参数),除了 Python 标准类型的相同 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 opcode 重载了操作码参数以对堆栈上的位置参数和关键字参数的数量进行编码,每个参数都编码为一个字节。

    【讨论】:

      【解决方案4】:

      这似乎是编译源代码的限制,因此可能只存在于直接传递的参数,而不是 *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 参数看起来应该只在调用端作为一个参数用于这些目的。

      【讨论】:

      • 过时的答案。该链接已损坏,并且从 Python 3.7 开始不会进行该检查。
      【解决方案5】:

      对于**kwargs,如果我没记错的话,这是一本字典。因此它几乎没有限制。

      对于*args,我不太确定,但我认为它是一个元组或一个列表,所以它也几乎没有限制。

      没有限制,我的意思是除了内存限制。

      【讨论】:

        【解决方案6】:

        我尝试了一个包含 4000 项的列表,并且成功了。所以我猜它也适用于更大的值。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-05-09
          • 1970-01-01
          • 2011-03-29
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多