2012-03-26 15 views
7

Duplicar posible:
The Python yield keyword explained¿Qué hace el rendimiento en Python 2.7?

Está bien, probablemente ha enunciado la pregunta mal, pero esta es la situación que tengo.

tengo esta línea de código en Python 2.7, que estoy tratando de entender:

yield (padding_zeros + number_string).encode("ascii") 

En esta línea de código, padding_zeros es una cadena de un número variable de '0 y number_string es un número en la forma de una cadena que puede ser cualquier número entre 0, digamos 10000.

Estoy bastante seguro de que el .encode("ascii") simplemente convierte la producción de rendimiento en ascii.

Lo que estoy completamente en el mar es lo que hace el yield (padding_zeros + number_string).

Sé que inicia un generador, pero he pasado mucho tiempo buscando en línea y leyendo sobre la sintaxis, pero todavía no puedo averiguar qué es lo que el generador realmente hace. No ayuda que esta sea la primera vez que miro python (mi objetivo final es convertir este código a C#).

Entonces, básicamente, ¿podría alguien explicarme qué hace esta línea de código? ¿Simplemente agrega las dos cuerdas o hace algo un poco más complicado?

Para más contexto, este es el bloque que esa línea de código aparece en:

for current_length in range(4, max_length + 1): 
    for i in range(0, pow(10, current_length)): 
     number_string = str(i) 
     padding_zeros = "0" * (current_length - len(number_string)) 
     yield (padding_zeros + number_string).encode("ascii") 

(max_length siendo exactamente lo que suena - un número que indica la longitud máxima de algo)

Gracias de antemano por todas las respuestas (incluso si me dicen que no sea un novato travieso) :)

EDIT: Gracias por las respuestas, aunque solo pude p ick one como la mejor respuesta, todos fueron muy útiles. Y gracias por los comentarios también, como algunos de ellos señalaron, What does the "yield" keyword do in Python? es una muy buena guía general de rendimiento, generadores e iteraciones, incluso si no encuentro una respuesta a mi situación específica :)

+0

¿Es esta Python 2 o Python 3? –

+0

Hola George, tu pregunta ha sido respondida aquí bastante bien. Siento: http://stackoverflow.com/questions/231767/the-python-yield-keyword-explicado – MattH

+0

Ver esta respuesta: http://stackoverflow.com/questions/231767/the-python-yield-keyword-explain/231855 # 231855 –

Respuesta

6

bien, sabes de generadores, por lo que la parte yield no necesita explicación . Multa.

Entonces, ¿qué hace esa línea en realidad? No mucho:

Concaten padding_zeros y number_string y luego codifica el resultado en ASCII. Que en Python 2.7 no es operativo porque la cadena es ASCII para empezar (solo consiste en dígitos ASCII, por definición).

En Python 3, sería diferente; aquí el .encode() habría convertido la cadena a un objeto bytes. Pero en Python 2, no tiene ningún sentido.

+0

Gracias - podría ser que este código se haya escrito originalmente en Python 3, lo que explicaría por qué aparece como no operativo en Python 2. No obstante, no puede ser 100% seguro. Gracias por su respuesta y lo siento por estar tan despistado. – GeorgePotter

1

En este El caso yield se usa para realizar una evaluación diferida. Los siguientes códigos son aproximadamente equivalentes:

def f(...): 
    for current_length in range(4, max_length + 1): 
     for i in range(0, pow(10, current_length)): 
      number_string = str(i) 
      padding_zeros = "0" * (current_length - len(number_string)) 
      yield (padding_zeros + number_string).encode("ascii") 

result = list(f()) 

frente

def f(...): 
    result = list() 
    for current_length in range(4, max_length + 1): 
     for i in range(0, pow(10, current_length)): 
      number_string = str(i) 
      padding_zeros = "0" * (current_length - len(number_string)) 
      result.append((padding_zeros + number_string).encode("ascii")) 
    return result 

result = f() 

Es posible que sólo siga el segundo en que la traducción del código.

+1

Excepto que la segunda versión devuelve una lista, mientras que el generador arrojará cada elemento uno por uno. – Marcin

+0

Muchas gracias :) – GeorgePotter

+0

@Marcin seguro. Pero no creo que OP se preocupe por eso :) –

3

yield es como volver en un generador.

En el punto en que se ejecuta yield, la ejecución de la función del generador se detiene y se devuelve el valor.La diferencia es que cuando se vuelve a invocar el generador, la ejecución se reinicia en la declaración de rendimiento, y continúa hasta que se produce otro rendimiento, o se produce una excepción (no controlada), o se golpea un return. El return o la excepción darán por terminado el generador.

El punto de un generador es que uno puede invocarlo como x = next(generator) o x = generator.next(), y cada vez uno recibirá el valor del rendimiento dentro del generador. Los generadores también son iterables, por lo que se pueden usar como fuente de un bucle: for x in generator: print x.

Al igual que en C#, el operador . invoca el método denominado a su derecha en el objeto que aparece a la izquierda del operador. Por consiguiente, (padding_zeros + number_string).encode("ascii") llama a encode en el resultado de (padding_zeros + number_string).

Para el significado de encode, ver aquí: http://docs.python.org/library/stdtypes.html#str.encode

Para la referencia del lenguaje (suponiendo que está utilizando Python 2): http://docs.python.org/reference/index.html

+1

Muchas gracias :) – GeorgePotter

+0

@GeorgePotter No hay problema. Siéntase libre de aceptar una respuesta, y vote por cualquier otra que encuentre útil (una vez que pueda votar). – Marcin

0

un generador es una máquina estatal que implementa la interfaz del iterador o __iter__ en python. esperará después de "rendimiento" hasta que llame a next() en él.

probar esto:

def my_gen(): 
    for current_length in range(4, max_length + 1): 
     for i in range(0, pow(10, current_length)): 
      number_string = str(i) 
      padding_zeros = "0" * (current_length - len(number_string)) 
      print "generate %s" % i 
      yield (padding_zeros + number_string).encode("ascii") 

for i in my_gen(): 
    print "iterate %s" % i 
+0

Un generador no es un statemachine -1: http://en.wikipedia.org/wiki/Finite-state_machine. Además, la interfaz del generador primario es 'next'. – Marcin

+0

creo que es (bastante simple): cada llamada a next() cambia su estado, lo que le permite avanzar o detenerse. (edité el segundo '__iter__' a 'next()') –

+0

Esa no es la definición de una máquina de estados. – Marcin