2009-04-03 3 views
27

Pythonの関数は最大256個の引数を持つことができることは多少の知識です。この制限は*args**kwargsに適用された場合にどのような私が知って興味はある彼らは、次のようにアンロールしているとき:、仮に、ケースリストがより大きく256の項目があるかもしれないので、私が尋ねるPython関数の引数の最大数はいくらですか?

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

def do_something(*items): 
    pass 

*argsまたは**kwargsのセットとして展開されます。

答えて

21

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

結論:いいえ、それは適用されませんアンロールされた議論に。

+0

制限が発信側にあるようです。 exec 'f(' + '、'。str(i)for range(5000))+ ')' – Brian

+0

"WFM"を試してみてください。 WTF?.... –

+0

@Stefan:* Works For Me * –

1

4000件のリストを試してみましたが、それはうまくいきました。だから私はそれが同様に大きな値のために動作すると思います。

1

** kwargsについては、私がよく覚えていれば、これは辞書です。したがって、制限はありません。

for * args、私はそれほど確かではありませんが、タプルまたはリストだと思うので、制限はありません。

制限がないため、メモリの制限を除いています。

+0

はい* argsはタプルです。 –

5

これはソースのコンパイルに制限があるようですので、おそらく引数が直接渡され、* argsや** kwargsには渡されません。

関連するコードはast.cで見つけることができます:

if (nargs + nkeywords + ngens > 255) { 
    ast_error(n, "more than 255 arguments"); 
    return NULL; 
} 

しかし、これはast_for_callであり、そしてこれだけ呼び出し側にapplysことに注意してください。すなわちf(a,b,c,d,e...)であるが、これは位置の(a,b,c,d)keyword (a=1, b=2, c=3)の両方のスタイルパラメータをカウントします。実際の*args**kwargsのパラメータは、呼び出し側でこれらの目的のために1つの引数として数えられるように見えます。

20

制限は、コンパイルされたバイトコードが位置引数および/またはキーワード引数を使用して関数を呼び出す方法によるものです。

バイトコードopは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から構成されます。これらのアイテムは受信者に直接渡され、必要に応じてアンロールされます。

+0

これはCPythonの実装上の制限ですか、それともPython自体の一部ですか? – EOL

+1

これは、CPythonバイトコードの実装の詳細です。 –

+0

...確かに。制限はCPython 3.7でリリースされる予定です。 – EOL

2

は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は両方をエンコードするためにオペコードの引数をオーバーロードされたため、この制限が整備されています。スタック上の位置引数とキーワード引数の数。両方とも1バイトでエンコードされます。

この制限は、今後のPython 3.7リリースでは削除されました。issue #27213およびissue #12844を参照してください。 #27213は、パフォーマンスとシンプルさのためにオペコードのCALL_FUNCTION*ファミリを改訂しました(3.6の一部)opcode引数を1つの引数の数だけエンコードして解放し、#12844はコンパイル時のチェックを削除し、 EXTENDED_ARG() opcodeと3.7で

は、今、あなたが明示的に引数を使用して渡すことができますどのように多くの引数のすべてのでは制限ありません、スタック(そう、あなたの記憶で今束縛)に取り付けることができますどのように多くの保存:

>>> 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)以外の制限はありません。

+0

新しい情報と文脈を提供する良いリフレッシュの答え – Rookie

関連する問題