working with what used print generators funcion for explicacion are python generator yield

with - what are python generators used for



¿Cómo puedo saber si un generador recién se inició? (3)

Esto solo funciona en Python 3.2+:

>>> def gen(): yield 0; yield 1 ... >>> a = gen() >>> import inspect >>> inspect.getgeneratorstate(a) ''GEN_CREATED'' >>> next(a) 0 >>> inspect.getgeneratorstate(a) ''GEN_SUSPENDED'' >>> next(a) 1 >>> inspect.getgeneratorstate(a) ''GEN_SUSPENDED'' >>> next(a) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration >>> inspect.getgeneratorstate(a) ''GEN_CLOSED''

Entonces, la función solicitada es:

import inspect def is_just_started(gen): return inspect.getgeneratorstate(gen) == inspect.GEN_CREATED:

Por curiosidad, busqué en CPython para descubrir cómo estaba determinando esto ... Aparentemente se ve en generator.gi_frame.f_lasti que es el "índice del último intento de instrucción en bytecode". Si es -1 entonces aún no ha comenzado.

Aquí hay una versión de py2:

def is_just_started(gen): return gen.gi_frame is not None and gen.gi_frame.f_lasti == -1

Me gustaría una función, is_just_started , que se comporte como la siguiente:

>>> def gen(): yield 0; yield 1 >>> a = gen() >>> is_just_started(a) True >>> next(a) 0 >>> is_just_started(a) False >>> next(a) 1 >>> is_just_started(a) False >>> next(a) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration >>> is_just_started(a) False

¿Cómo puedo implementar esta función?

Miré el atributo .gi_running pero parece ser usado para otra cosa.

Si conozco el primer valor que debe enviarse al generador, puedo hacer algo como esto:

def safe_send(gen, a): try: return gen.send(a) except TypeError as e: if "just-started" in e.args[0]: gen.send(None) return gen.send(a) else: raise

Sin embargo, esto parece aborrecible.


Haga un nuevo generador que simplemente rinda de su generador de interés. Establece un indicador una vez que se ha consumido el primer valor . Después, simplemente puede usar el yield from resto de los artículos.

Utilice el generador sustituto como sustituto del generador que le interesa para supervisar el estado "is_just_started".

Esta técnica no es intrusiva y se puede usar incluso en generadores para los cuales no tiene control sobre el código fuente.


Puede crear un iterador y establecer el indicador como la propiedad de la instancia en la clase de iterador como:

class gen(object): def __init__(self, n): self.n = n self.num, self.nums = 0, [] self.is_just_started = True # Your flag def __iter__(self): return self # Python 3 compatibility def __next__(self): return self.next() def next(self): self.is_just_started = False # Reset flag with next if self.num < self.n: cur, self.num = self.num, self.num+1 return cur else: raise StopIteration()

Y su función de verificación de valor sería como:

def is_just_started(my_generator): return my_generator.is_just_started

Muestra de ejecución:

>>> a = gen(2) >>> is_just_started(a) True >>> next(a) 0 >>> is_just_started(a) False >>> next(a) 1 >>> is_just_started(a) False >>> next(a) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 19, in next StopIteration

Para saber la diferencia entre el iterador y el generador , verifique la diferencia entre los generadores de Python y los iteradores