2010-07-08 19 views
5

Esta pregunta va a ser bastante larga, por lo que me disculpo preventivamente.argumentos posicionales en exceso, desempaquetar listas de argumentos o tuplas, y desempaquetado iterativo extendido

En Python podemos utilizar * en los tres casos siguientes:

I. Al definir una función que queremos ser exigible con un número arbitrario de argumentos, como in this example:

def write_multiple_items(file, separator, *args): 
    file.write(separator.join(args)) 

En este caso, los argumentos posicionales en exceso se recopilan en una tupla .

II. El caso inverso es cuando los argumentos ya están en cualquiera de una lista o una tuplay deseamos desempaquetar los archivos para una llamada a una función que requiere argumentos posicionales separados, tales como in this example:

>>> range(3, 6)    # normal call with separate arguments 
[3, 4, 5] 
>>> args = [3, 6] 
>>> range(*args)   # call with arguments unpacked from a list 
[3, 4, 5] 

III. Comenzando con Python 3, * también se utiliza en el contexto de extendida lista o tupla desembalaje, tales como in this example para tuplas:

>>> a, *b, c = range(5) 
>>> b 
[1, 2, 3] 

o para las listas:

>>> [a, *b, c] = range(5) 
>>> b 
[1, 2, 3] 

En tanto casos, todos los elementos del paquete iterable desempaquetado que no están asignados a ninguna de las expresiones obligatorias se asignan a una lista .

Así que aquí está la cuestión: en caso de que los argumentos adicionales se recogen en una tupla, mientras que en caso III los artículos adicionales son asignados a una lista. ¿De dónde esta discrepancia? La única explicación que pude encontrar fue en el PEP 3132 que dice que:

Posibles cambios discutidos fueron:

[...]

hacer que el objetivo estrellado una tupla en lugar de una lista . Esto sería consistente con * args de una función, pero hace que el procesamiento posterior del resultado sea más difícil.

Sin embargo, desde una perspectiva pedagógica esta falta de consistencia es problemático, sobre todo teniendo en cuenta que si desea procesar el resultado, siempre se podría decir que la lista (b) (suponiendo que b en los ejemplos anteriores era una tupla) ¿Me estoy perdiendo de algo?

Respuesta

7

En Python podemos utilizar * en los tres casos siguientes:

Usted quiere decir prefijo*, por supuesto - infija* se usa para la multiplicación.

Sin embargo, desde un perspectiva pedagógica esta falta de consistencia es problemático, sobre todo teniendo en cuenta que si desea procesar el resultado, siempre se puede decir que la lista (b) (suponiendo b en los ejemplos anteriores era una tupla). ¿Me estoy perdiendo algo?

Yo diría que el problema de diseño (antiguo y muy largo en el diente) es con el hecho de que cuando recibes argumentos arbitrarios los consigues como una tupla, cuando una lista sería más útil en muchos casos sin inconvenientes reales (la pequeña cantidad de procesamiento adicional y memoria que puede ser necesaria para hacer una lista en lugar de una tupla es insignificante en el contexto de la sobrecarga de llamadas de función - o desempaquetando secuencias, para el caso; el procesamiento adicional y la memoria necesaria para hacer una lista , así como una tupla es realmente más molesto).

Hay muy poco que se puede hacer con una tupla pero no una lista; básicamente, simplemente hash (para usar como elemento de conjunto o dict), mientras que una lista ofrece mucha más funcionalidad adicional, y no solo para modificarlo ... métodos como count y index también son útiles.

+0

Gracias por la respuesta. En pocas palabras, lo que estoy escuchando es que el caso ** I ** debería haber sido diseñado para dar una lista. –

+0

@Alexandros, esa es en verdad mi opinión, pero por supuesto la retrospectiva es 20/20, y esa decisión se tomó ... No estoy seguro de cuándo, pero ya estaba en Python 1.5.2, hace más de 11 años. –

8

Has perdido una.

IV. Además, en Python 3, un * desnudo en la lista de argumentos marca el final de los argumentos posicionales, lo que permite keyword-only arguments.

def foo(a, b, *, key = None): 
    pass 

Esto puede ser llamado foo(1, 2, key = 3) pero no foo(1, 2, 3).

+0

Gracias. Aunque no es realmente una respuesta a mi pregunta, es bueno tener todos los casos reunidos en un hilo. –

Cuestiones relacionadas