2011-07-16 9 views
14

Antes de decir una palabra, permítanme agradecer a la comunidad por ser la ubicación autorizada para mis consultas de programación recientes. Y pretende que esos elogios no se expresaron con palabras. De todos modos, la ley de la probabilidad dictó que tropecé con algo que no pude encontrar utilizando la versátil barra de búsqueda, así que decidí preguntar explícitamente por primera vez. Tal vez no estaba buscando usando Pythonic: suficiente jerga. O tal vez sea una mierda en Google/Stackoverflowing. Independientemente de ...Python: ¿Rendimiento Dict Elements en la producción de Coroutines?

Estoy jugando con corotines y generadores de Python. Por lo que puedo deducir, puedes hacer cualquier cosa que un generador-comprensión pueda con corutinas de productores, aunque de forma más amplia. Actualmente estoy usando Python 3, aunque cualquier respuesta con respecto a Python 2 tampoco sería un error.

así que estoy asumiendo los siguientes fragmentos de código son equivalentes:

one_to_three = (num for num in range(1, 4)) 

...

def one_to_three(): 
    for num in range(1, 4): 
     yield num 

one_to_three_gen = one_to_three() 

Funciona en mi instalación de Python. Si ignoro la redundancia-tan-común-en-los ejemplos que aparecen en ese código, veo que la comprensión del generador se asigna fácilmente al generador hecho por el productor coroutine. Siendo el Dr. pragmático, he intentado asignar el mismo concepto a dicts, dado que por comprensión dict ya existen, la hizo pensar que estos dos sería equivalente:

one_to_three_doubles = {num : num * 2 for num in range(1, 4)} 

...

def one_to_three_doubles(): 
    for num in range(1, 4): 
     yield num : num * 2 

one_to_three_doubles_gen = one_to_three_doubles() 

La primera de ellas funciona, pero el segundo no. Indica un error de sintaxis en los dos puntos en la 3ra línea.

Ahora, o me estoy deslizando muy poco en la sintaxis, o tengo un malentendido masivo de cómo funcionan las coroutines de producción. Sospecho que está fallando por la misma razón por la que no puedes hacer que una corutina devuelva una lista en lugar de un generador, pero realmente no lo sé.

Así que sí, una solución a ese error es básicamente lo que estoy pidiendo; gracias por adelantado. Preferiría una respuesta que me diga la respuesta en lugar de darme una forma completamente nueva de lograr el resultado, pero obviamente, si es la única forma ...

+0

Usted está hablando de generadores, no coroutines.Si quieres saber que realmente se leen corutinas [Un curso curioso sobre Corutinas y simultaneidad] (http://www.dabeaz.com/coroutines). –

+0

Pensé que había corutinas productoras y consumidoras, y que usar el patrón de rendimiento para crear una secuencia era un uso simplista de corutinas para crear expresiones de generador, dado que la ejecución se detiene y se reanuda al ceder cada valor, que es ¿Cómo rastrea dónde está? Sin embargo, podría estar equivocado. – Louis

Respuesta

16

Comprensiones dictonas funcionan como lista/conjunto de comprensiones y generador expresiones - una comprensión de X con un "cuerpo" de expr for vars in iterable es prácticamente equivalente a X(expr for vars in iterable) - y usted ya sabe cómo convertir una expresión de generador en un generador. Pero tenga en cuenta el bit "bonito", ya que una traducción literal no funciona (como ha notado) y no es necesaria en absoluto (no hace la implementación mucho más fácil y en realidad sería bastante hacky).

Dict comprensión solo tiene un poquito de azúcar sintáctico para parecerse más a los literales dict (el colon). Semánticamente, no es necesario, no hay nada especial al respecto. Detente y piensa por un segundo: la comprensión dict debe producir dos valores en cada iteración, una clave y un valor. Eso es exactamente lo que significa el colon - (key, value) pares (recuerde que dict acepta un iterable de (key, value) pares). No puede usar ese azúcar sintáctico fuera de las comprensiones dict, pero puede usar tuplas para los pares. Por lo tanto, el generador equivalente sería:

def one_to_three_doubles(): 
    for num in range(1, 4): 
     yield num, num * 2 
+0

Ajá, eso es exactamente lo que quería saber; Gracias por la pronta respuesta. Tiene sentido cuando lo dices así, y 'hace clic' cuando mencionas que dict acepta una iterable de pares. – Louis

Cuestiones relacionadas