Python関数は最大256個の引数を持つことができるということは、いくぶん一般的な知識です。私が知りたいのは、この制限が*args
と**kwargs
に適用されるかどうかです。 '次の方法で展開されます:
items = [1,2,3,4,5,6]
def do_something(*items):
pass
仮に、256項目を超えるリストが*args
または**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))
>>>
結論:いいえ、展開された引数には適用されません。
制限は、コンパイルされたバイトコードが位置引数やキーワード引数を使用した関数の呼び出しをどのように処理するかによるものです。
問題のバイトコード操作はCALL_FUNCTION
で、長さ4バイトのop_arg
を伝送しますが、最下位2バイトが使用されます。これらのうち、最上位バイトはスタック上のキーワード引数の数を表し、最下位バイトはスタック上の位置引数の数を表します。したがって、最大で0xFF == 255
キーワード引数または0xFF == 255
位置引数を持つことができます。
この制限は、*args
および**kwargs
には適用されません。これは、その文法を使用する呼び出しでは、署名に応じてバイトコードops CALL_FUNCTION_VAR
、CALL_FUNCTION_KW
、およびCALL_FUNCTION_VAR_KW
が使用されるためです。これらのオペコードの場合、スタックは*args
の反復可能オブジェクトと**kwargs
のdict
で構成されます。これらのアイテムは、必要に応じて展開するレシーバーに直接渡されます。
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
_サイズ制限以外の制限はありません。
これはソースのコンパイルにおける制限のように思われるため、* 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つの引数としてのみカウントする必要があるように見えます。
** kwargsの場合、よく覚えていれば、これは辞書です。したがって、制限はほとんどありません。
* argsについては、よくわかりませんが、タプルまたはリストだと思うので、制限もありません。
制限がないということは、おそらくメモリ制限を除いて意味します。
4000アイテムのリストを試してみましたが、うまくいきました。したがって、より大きな値でも機能すると思います。