web-dev-qa-db-ja.com

Python関数の引数の最大数はいくつですか?

Python関数は最大256個の引数を持つことができるということは、いくぶん一般的な知識です。私が知りたいのは、この制限が*args**kwargsに適用されるかどうかです。 '次の方法で展開されます:

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

def do_something(*items):
    pass

仮に、256項目を超えるリストが*argsまたは**kwargsのセットとして展開される場合があるためです。

31
Soviut

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

結論:いいえ、展開された引数には適用されません。

23
vartec

制限は、コンパイルされたバイトコードが位置引数やキーワード引数を使用した関数の呼び出しをどのように処理するかによるものです。

問題のバイトコード操作はCALL_FUNCTIONで、長さ4バイトのop_argを伝送しますが、最下位2バイトが使用されます。これらのうち、最上位バイトはスタック上のキーワード引数の数を表し、最下位バイトはスタック上の位置引数の数を表します。したがって、最大で0xFF == 255キーワード引数または0xFF == 255位置引数を持つことができます。

この制限は、*argsおよび**kwargsには適用されません。これは、その文法を使用する呼び出しでは、署名に応じてバイトコードops CALL_FUNCTION_VARCALL_FUNCTION_KW、およびCALL_FUNCTION_VAR_KWが使用されるためです。これらのオペコードの場合、スタックは*argsの反復可能オブジェクトと**kwargsdictで構成されます。これらのアイテムは、必要に応じて展開するレシーバーに直接渡されます。

22
Chris Colbert

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 がopcode引数をオーバーロードして、スタック上の位置引数とキーワード引数の両方の数をエンコードするため、この制限が適用されます。 、それぞれが1バイトでエンコードされます。

この制限は、今後のPython 3.7リリースで削除されます。 issue#2721 および 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_キャッチオールパラメーターを使用する場合は、それらに注意してください。 制限されています。

_*args_および_**kwargs_呼び出し構文(引数の拡張)の場合、Python標準タイプに同じ_sys.maxint_サイズ制限以外の制限はありません。

12
Martijn Pieters

これはソースのコンパイルにおける制限のように思われるため、* 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つの引数としてのみカウントする必要があるように見えます。

5
Brian

** kwargsの場合、よく覚えていれば、これは辞書です。したがって、制限はほとんどありません。

* argsについては、よくわかりませんが、タプルまたはリストだと思うので、制限もありません。

制限がないということは、おそらくメモリ制限を除いて意味します。

1
Martin

4000アイテムのリストを試してみましたが、うまくいきました。したがって、より大きな値でも機能すると思います。

0
Geo