Tengo un generador en mi método get_new_point que recupera una tupla de datos de un marco de datos dentro de un dict. Idealmente, cuando ejecuto el método update_trailing_points, recuperaría la próxima tupla del generador. Sin embargo, cuando realmente ejecuto el método update_trailing_points, devuelve la misma tupla cada vez (la primera línea del marco de datos). ¿Qué estoy haciendo mal aquí?

Permítanme explicar mis estructuras de datos porque sé que pueden ser un poco confusas:

All_data es un dict de dataframes. Las teclas son 'símbolos'

Symbol_list es una lista de las claves (símbolos)

    def get_new_point(self,symbol):
        for i in self.all_data[symbol].index:
            yield tuple([self.all_data[symbol]['timestamp'][i],\ 
                         self.all_data[symbol]['point'][i])

    def update_trailing_points(self):
        for s in self.symbol_list:
            try:
                new_point = self.get_new_point(s).__next__()
            except StopIteration:
                self.continue_test = False
2
Broadway 10 may. 2019 a las 02:01

3 respuestas

La mejor respuesta

self.get_new_point(s) devuelve un objeto generador.

new_point = self.get_new_point(s).__next__()

Estás reiniciando el generador cada vez que se ejecuta este código. Debería realizar la llamada self.get_new_point(s) solo una vez, pero __next__() en ese objeto varias veces.

1
rdas 9 may. 2019 a las 23:07

FWIW, tu get_new_point se puede "mejorar":

def make_point_generator(self, symbol):
    df = self.all_data[symbol][['timestamp', 'point']]
    yield from df.itertuples(index=False)

¡Sería recomendable utilizar la funcionalidad pandas directamente siempre que sea posible!

Supongo que quieres un generador de puntos. Luego:

def __init__(self):
    self.__gens = None

def update_trailing_points(self):
    if self.__gens is None:
        self.__gens = {s: self.make_point_generator(s) for s in self.symbol_list}

    for s in self.symbol_list:
        try:
            new_point = next(self.__gens[s])
        except StopIteration:
            self.continue_test = False
0
Mateen Ulhaq 9 may. 2019 a las 23:49

Así no se usan los generadores. Mira esto:

def test(n):
    for i in range(10):
        yield i

# bad: creates a new generator every time.
n = 10
for i in range(n):
    print(test(n).__next__())

# good: creates a single generator then iterates over it
n = 10
t = test(n)
for i in range(n):
    print(next(t))
0
Julien 9 may. 2019 a las 23:08