while simbolos significa relacionales que operadores not else ejemplos bucles python list-comprehension

simbolos - Lista de comprensión sin[] en Python



simbolos en python (7)

Unirse a una lista:

>>> ''''.join([ str(_) for _ in xrange(10) ]) ''0123456789''

join debe tomar un iterable.

Aparentemente, el argumento de join es [ str(_) for _ in xrange(10) ] , y es una lista de comprensión .

Mira este:

>>>''''.join( str(_) for _ in xrange(10) ) ''0123456789''

Ahora, el argumento join es simplemente str(_) for _ in xrange(10) , no [] , pero el resultado es el mismo.

¿Por qué? ¿ str(_) for _ in xrange(10) también produce una lista o un iterable?


Como se mencionó, es una expresión generadora .

De la documentación:

Los paréntesis pueden omitirse en llamadas con solo un argumento. Ver la sección Llamadas para el detalle.


El argumento para su segunda llamada de join es una expresión generadora. Sí produce un iterable.


Eso es un generador, en lugar de una lista de comprensión. Los generadores también son iterables, pero en lugar de crear la lista completa primero y luego pasarla para unirse, pasa cada valor en el rango uno por uno, lo que puede ser mucho más eficiente.


Los otros encuestados respondieron correctamente que usted había descubierto una expresión de generador (que tiene una notación similar a la de la lista pero sin los corchetes que la rodean).

En general, las genexps (como se las conoce cariñosamente) son más eficientes en cuanto a la memoria y más rápidas que las listas de comprensión.

SIN EMBARGO, es el caso de ''''.join() , una comprensión de la lista es más rápida y más eficiente con la memoria. La razón es que join necesita hacer dos pasadas sobre los datos, por lo que realmente necesita una lista real. Si le das uno, puede comenzar su trabajo de inmediato. Si le da un genexp en su lugar, no puede comenzar a trabajar hasta que construya una nueva lista en la memoria ejecutando el genexp hasta el agotamiento:

~ $ python -m timeit ''"".join(str(n) for n in xrange(1000))'' 1000 loops, best of 3: 335 usec per loop ~ $ python -m timeit ''"".join([str(n) for n in xrange(1000)])'' 1000 loops, best of 3: 288 usec per loop

El mismo resultado se mantiene al comparar itertools.imap versus map :

~ $ python -m timeit -s''from itertools import imap'' ''"".join(imap(str, xrange(1000)))'' 1000 loops, best of 3: 220 usec per loop ~ $ python -m timeit ''"".join(map(str, xrange(1000)))'' 1000 loops, best of 3: 212 usec per loop


Si está en parens, pero no en corchetes, es técnicamente una expresión generadora. Las expresiones de generador se introdujeron por primera vez en Python 2.4.

http://wiki.python.org/moin/Generators

La parte después de la unión, ( str(_) for _ in xrange(10) ) es, por sí misma, una expresión generadora. Podrías hacer algo como:

mylist = (str(_) for _ in xrange(10)) ''''.join(mylist)

y significa exactamente lo mismo que usted escribió en el segundo caso anterior.

Los generadores tienen algunas propiedades muy interesantes, una de las cuales es que no terminan asignando una lista completa cuando no la necesita. En cambio, una función como unirse "bombea" los elementos fuera de la expresión del generador de a uno por vez, haciendo su trabajo en las partes intermedias pequeñas.

En sus ejemplos particulares, la lista y el generador probablemente no funcionan de forma terriblemente diferente, pero en general, prefiero usar expresiones de generador (e incluso funciones de generador) cada vez que puedo, sobre todo porque es extremadamente raro que un generador sea más lento que una lista completa materialización.


Su segundo ejemplo utiliza una expresión de generador en lugar de una lista de comprensión. La diferencia es que con la lista de comprensión, una lista se construye completamente y se pasa a .join() . Con la expresión del generador, los elementos se generan uno por uno y son consumidos por .join() . Este último usa menos memoria y generalmente es más rápido.

Da la casualidad que el constructor de lista consumirá cualquier iterable, incluida una expresión de generador. Asi que:

[str(n) for n in xrange(10)]

es solo "azúcar sintáctico" para:

list(str(n) for n in xrange(10))

En otras palabras, una lista de comprensión es solo una expresión generadora que se convierte en una lista.


>>>''''.join( str(_) for _ in xrange(10) )

Esto se llama expresión de generador y se explica en PEP 289 .

La principal diferencia entre las expresiones del generador y las comprensiones de la lista es que las primeras no crean la lista en la memoria.

Tenga en cuenta que hay una tercera forma de escribir la expresión:

''''.join(map(str, xrange(10)))