Сколько аргументов может быть передано функции в Python? [Дубликат]

Случай, когда примечание [] полезно:

Если ваш объект является динамическим, и могут быть некоторые случайные значения в таких ключах, как number и [] или любой другой специальный символ, например -

var a = { 1 : 3 };

Теперь, если вы попытаетесь получить доступ, как a.1, он будет через ошибку, потому что он ожидает строку там.

27
задан SilentGhost 3 April 2009 в 16:45
поделиться

6 ответов

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

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

21
ответ дан Eric Lebigot 24 August 2018 в 17:30
поделиться
  • 1
    Похоже, что предел на вызывающей стороне. Попробуйте exec 'f (' + ','. Join (str (i) для i в диапазоне (5000)) + ')' – Brian 3 April 2009 в 17:42
  • 2
    & Quot; WFM & Quot ;? WTF? .... – Stefan Pochmann 1 January 2018 в 17:43
  • 3
    @Stefan: Работает для меня – Martijn Pieters♦ 2 January 2018 в 02:00

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

5
ответ дан Brian 24 August 2018 в 17:30
поделиться

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

0
ответ дан Geo 24 August 2018 в 17:30
поделиться

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

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

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

21
ответ дан Kasramvd 24 August 2018 в 17:30
поделиться
  • 1
    Является ли это ограничением реализации CPython или является частью самого Python? – Eric Lebigot 11 June 2017 в 05:00
  • 2
    Это деталь реализации байт-кода CPython. – Chris Colbert 19 July 2017 в 03:18
  • 3
    … в самом деле. Ограничение будет выпущено с помощью Python 3.7. – Eric Lebigot 19 July 2017 в 08:16

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

Это ограничение удалено в предстоящей версии Python 3.7, см. issue # 27213 и issue # 12844 ; # 27213 переработал семейство кодов опций CALL_FUNCTION* для производительности и простоты (часть 3.6), освободив аргумент аргумента opcode только для кодирования одного аргумента, а # 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 и **kwargs вызова (расширения аргументов) нет ограничений, кроме тех же sys.maxint ограничений размера для стандартных типов Python.

8
ответ дан Martijn Pieters 24 August 2018 в 17:30
поделиться
  • 1
    Хороший ответ об обновлении, предоставляющий новую информацию и контекст – Rookie 1 January 2018 в 18:24

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

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

Без ограничений я имею в виду, кроме, возможно, ограничения памяти.

1
ответ дан S.Lott 24 August 2018 в 17:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: