2009-04-03 17 views
27

Es de conocimiento común que las funciones de Python pueden tener un máximo de 256 argumentos. Lo que tengo curiosidad por saber es si este límite se aplica a *args y **kwargs cuando se desenrollan de la siguiente manera:¿Cuál es la cantidad máxima de argumentos en una función de Python?

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

def do_something(*items): 
    pass 

lo pregunto porque, hipotéticamente, puede haber casos en que una lista más amplia de 256 artículos se desenrolla como un conjunto de *args o **kwargs.

Respuesta

21

WFM

>>> fstr = 'def f(%s): pass' % (', '.join(['arg%d' % i for i in range(5000)])) 
>>> exec(fstr) 
>>> f 
<function f at 0x829bae4> 

Actualización: como Brian se dio cuenta, el límite está en el lado llamante:

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

por otro lado, esto funciona:

>>> f(*range(5000)) 
>>> 

Conclusión: no, no se aplica para desenrollar los argumentos.

+0

Parece que el límite está en el lado de la llamada. Pruebe exec 'f (' + ','. Join (str (i) for i in range (5000)) + ')' – Brian

+0

"WFM"? ¿WTF? .... –

+0

@Stefan: * Works For Me * –

1

He intentado para una lista de 4000 artículos, y funcionó. Así que supongo que funcionará también para valores más grandes.

1

para ** kwargs, si recuerdo bien, este es un diccionario. Por lo tanto, no tiene límites.

por * args, no estoy tan seguro, pero creo que es una tupla o una lista, por lo que tampoco tiene límites.

Me refiero sin límites, excepto quizás el límite de memoria.

+0

Sí * args es una tupla. –

5

Esto parece ser una restricción en la compilación de la fuente, por lo que probablemente exista solo para argumentos que se pasen directamente, no en * args o ** kwargs.

El código en cuestión puede encontrarse en ast.c:

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

Pero tenga en cuenta que esto es en ast_for_call, por lo que sólo applys al lado llamante. es decir, f(a,b,c,d,e...), en lugar de la definición, aunque contará los parámetros de estilo posicional (a,b,c,d) y keyword (a=1, b=2, c=3). Los parámetros reales *args y **kwargs parecen que solo deben contar como un argumento para estos propósitos en el lado de la llamada.

20

El límite se debe a la forma en que el bytecode compilado trata de llamar a una función con argumentos de posición y/o argumentos de palabra clave.

La operación de bytecode de preocupación es CALL_FUNCTION que lleva un op_arg que tiene 4 bytes de longitud, pero en los dos bytes menos significativos se usan. De ellos, el byte más significativo representa la cantidad de argumentos de palabra clave en la pila y el byte menos significativo el número de argumentos de posición en la pila. Por lo tanto, puede tener como máximo 0xFF == 255 argumentos clave o 0xFF == 255 argumentos posicionales.

Este límite no se aplica a * args y ** kwargs porque las llamadas con esa gramática usan las operaciones de bytecode CALL_FUNCTION_VAR, CALL_FUNCTION_KW y CALL_FUNCTION_VAR_KW dependiendo de la firma. Para estos códigos de operación, la pila consta de un iterable para los * args y un dict para los ** kwargs. Estos artículos se pasan directamente al receptor que los desenrolla según sea necesario.

+0

¿Es esta una restricción de implementación de CPython, o es parte de Python? – EOL

+1

Es un detalle de implementación del bytecode CPython. –

+0

... de hecho. La limitación se lanzará con CPython 3.7. – EOL

2

CPython tiene un límite de 255 argumentos pasados ​​explícitamente en una llamada:

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

Esta limitación está en su lugar porque hasta Python 3.5, el CALL_FUNCTION opcode sobrecargado el argumento opcode para codificar tanto la. número de argumentos posicionales y de palabra clave en la pila, ambos codificados en un solo byte.

Esta limitación se elimina en la próxima versión de Python 3.7, consulte issue #27213 y issue #12844; # 27213 reformuló la familia de códigos de operación CALL_FUNCTION* para rendimiento y simplicidad (parte de 3.6), liberando el argumento de código de operación para codificar solo un recuento de un solo argumento, y # 12844 eliminó la verificación en tiempo de compilación que impidió que se compilara más código.

En 3.7, con el EXTENDED_ARG() opcode, no hay ahora hay límite en absoluto de la cantidad de argumentos que puede pasar en el uso de argumentos explícitos, guardar el número puede ser instalado en la pila (tan ligada ahora por la memoria):

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

hacer la nota que las listas, tuplas y diccionarios se limitan a sys.maxsize elementos, por lo que si la función llamada utiliza *args y/o **kwargs de captura-todos los parámetros a continuación, los son limitadas.

Para la sintaxis de llamada *args y **kwargs (argumentos de expansión) no hay límites que no sean los mismos límites de tamaño sys.maxint en los tipos estándar de Python.

+0

Buena respuesta de actualización que proporciona nueva información y contexto – Rookie

Cuestiones relacionadas