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