¿Por qué no hay comprensión de tupla en Python?


Como todos sabemos, hay comprensión de lista, como

[i for i in [1, 2, 3, 4]]

Y hay comprensión de diccionario, como

{i:j for i, j in {1: 'a', 2: 'b'}.items()}

Pero

(i for i in (1, 2, 3))

Terminará en un generador, no en una comprensión tuple. ¿Por qué es eso?

Mi conjetura es que un tuple es inmutable, pero esta no parece ser la respuesta.

Author: Shady Xu, 2013-06-05

10 answers

Puede usar una expresión generadora:

tuple(i for i in (1, 2, 3))

Pero los paréntesis ya fueron tomados para.. expresiones generadoras.

 290
Author: Martijn Pieters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-26 18:17:15

Raymond Hettinger (uno de los desarrolladores del núcleo de Python) dijo esto sobre las tuplas en un tuit reciente :

#sugerencia de python:Generalmente, las listas son para bucles; las tuplas para estructuras. Las listas son homogéneas; las tuplas heterogéneas.Listas de longitud variable.

Esto (para mí) apoya la idea de que si los elementos de una secuencia están lo suficientemente relacionados como para ser generados por un, bueno, generador, entonces debería ser una lista. Aunque una tupla es iterable y parece simplemente un lista inmutable, es realmente el equivalente en Python de una estructura C:

struct {
    int a;
    char b;
    float c;
} foo;

struct foo x = { 3, 'g', 5.9 };

Se convierte en Python

x = (3, 'g', 5.9)
 53
Author: chepner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-21 20:03:36

Desde Python 3.5, también puedes usar la sintaxis de desempaquetado para una comprensión de tupla:

*(x for x in range(10)),
 25
Author: czheo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-26 18:21:16

La comprensión funciona haciendo loop o iterando sobre elementos y asignándolos a un contenedor, una Tupla no puede recibir asignaciones.

Una vez que se crea una tupla, no se puede anexar, extender o asignar a. La única manera de modificar una tupla es si uno de sus objetos puede ser asignado a (es un contenedor no-tupla). Porque la Tupla solo contiene una referencia a ese tipo de objeto.

También - una tupla tiene su propio constructor tuple() que se puede dar a cualquier iterador. Lo que significa que para crear una tupla, puedes hacer:

tuple(i for i in (1,2,3))
 18
Author: Inbar Rose,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-05 13:20:28

Mi mejor conjetura es que se quedaron sin corchetes y no pensaron que sería lo suficientemente útil para warrent agregar una sintaxis "fea"...

 11
Author: mgilson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-05 12:45:55

Como otro poster macm mencionado , la forma más rápida de crear una tupla a partir de un generador es tuple([generator]).


Comparación de rendimiento

  • Comprensión de la lista:

    $ python3 -m timeit "a = [i for i in range(1000)]"
    10000 loops, best of 3: 27.4 usec per loop
    
  • Tupla de comprensión de lista:

    $ python3 -m timeit "a = tuple([i for i in range(1000)])"
    10000 loops, best of 3: 30.2 usec per loop
    
  • Tupla del generador:

    $ python3 -m timeit "a = tuple(i for i in range(1000))"
    10000 loops, best of 3: 50.4 usec per loop
    
  • Tupla de desempaquetado:

    $ python3 -m timeit "a = *(i for i in range(1000)),"
    10000 loops, best of 3: 52.7 usec per loop
    

Mi versión de python:

$ python3 --version
Python 3.6.3

Así que siempre debes crear una tupla a partir de una lista comprensión a menos que el rendimiento no sea un problema.

 9
Author: Tom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-02 23:32:55

Las tuplas no pueden añadirse eficientemente como una lista.

Así que una comprensión de tupla necesitaría usar una lista internamente y luego convertirla en una tupla.

Eso sería lo mismo que lo que haces ahora: tupla ([comprensión])

 3
Author: macm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-15 21:33:12

Creo que es simplemente por el bien de la claridad, no queremos saturar el lenguaje con demasiados símbolos diferentes. También una comprensión tuple nunca es necesaria, una lista solo se puede usar en su lugar con diferencias de velocidad insignificantes, a diferencia de una comprensión dict en oposición a una comprensión de lista.

 2
Author: jamylak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-05 12:47:24

Los paréntesis no crean una tupla. aka uno = (dos) no es una tupla. La única manera es uno = (dos,) o uno = tupla (dos). Así que una solución es:

tuple(i for i in myothertupleorlistordict) 
 1
Author: ilias iliadis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-03 12:06:23

Podemos generar tuplas a partir de una comprensión de lista. El siguiente añade dos números secuencialmente en una tupla y da una lista de números 0-9.

>>> print k
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
>>> r= [tuple(k[i:i+2]) for i in xrange(10) if not i%2]
>>> print r
[(0, 1), (2, 3), (4, 5), (6, 7), (8, 9)]
 -1
Author: Rohit Malgaonkar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-27 19:06:01