Каково максимальное количество аргументов в функции Python? - PullRequest
30 голосов
/ 03 апреля 2009

Известно, что функции Python могут иметь максимум 256 аргументов. Мне интересно знать, применяется ли этот предел к *args и **kwargs, когда они развернуты следующим образом:

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

def do_something(*items):
    pass

Я спрашиваю, потому что, гипотетически, могут быть случаи, когда список, превышающий 256 элементов, развертывается как набор *args или **kwargs.

Ответы [ 6 ]

23 голосов
/ 03 апреля 2009

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

Вывод: нет, это не относится к развернутым аргументам.

22 голосов
/ 19 января 2012

Ограничение связано с тем, как скомпилированный байт-код обрабатывает вызов функции с аргументами позиции и / или аргументами ключевых слов.

Определяющим байт-кодом является CALL_FUNCTION, который содержит op_arg длиной 4 байта, но используются два младших байта. Из них старший значащий байт представляет количество аргументов ключевого слова в стеке, а наименее значимый - число позиционных аргументов в стеке. Следовательно, вы можете иметь не более 0xFF == 255 аргументов ключевых слов или 0xFF == 255 позиционных аргументов.

Это ограничение не распространяется на *args и **kwargs, поскольку в вызовах с этой грамматикой используются байт-коды ops CALL_FUNCTION_VAR, CALL_FUNCTION_KW и CALL_FUNCTION_VAR_KW в зависимости от сигнатуры. Для этих кодов операций стек состоит из итераций для *args и dict для **kwargs. Эти предметы передаются непосредственно получателю, который при необходимости развертывает их.

10 голосов
/ 01 января 2018

В версиях, предшествующих 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 перегружал аргумент опкода для кодирования как количества позиционных, так и ключевых аргументов в стеке, каждый из которых был закодирован в один байт.

Это ограничение будет снято в следующем выпуске Python 3.7, см. проблемы # 27213 и проблемы # 12844 ; # 27213 переработал семейство кодов операций CALL_FUNCTION* для повышения производительности и простоты (часть 3.6), освободив аргумент кода операции для кодирования только одного аргумента, и # 12844 удалил проверку во время компиляции, которая препятствовала использованию кода с большим количеством аргументов скомпилирован.

В 3.7 с опкодом EXTENDED_ARG() теперь вообще нет ограничения на то, сколько аргументов вы можете передать с использованием явных аргументов, за исключением того, сколько можно подогнать в стек (теперь он связан вашей памятью):

>>> 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 и **kwargs (расширяющие аргументы) нет никаких ограничений, кроме тех же ограничений размера sys.maxint для стандартных типов Python.

5 голосов
/ 03 апреля 2009

Похоже, что это ограничение при компиляции источника, поэтому, вероятно, будет существовать только для передаваемых аргументов напрямую, а не в * 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 выглядят так, как будто они должны считаться только одним аргументом для этих целей на вызывающей стороне.

1 голос
/ 03 апреля 2009

для ** kwargs, если я хорошо помню, это словарь. Поэтому он не имеет никаких ограничений.

для * args, я не совсем уверен, но я думаю, что это кортеж или список, поэтому он также не имеет ограничений.

Я имею в виду без ограничений, за исключением, может быть, ограничения памяти.

0 голосов
/ 03 апреля 2009

Я попытался получить список из 4000 элементов, и это сработало. Я предполагаю, что это будет работать и для больших значений.

...