es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

utilizando zip(*tuple_iterator) sin consumir el tuple_iterator en esta línea

Tengo un tuple_iterator : Iterator[Tuple[A, B]] y quiero obtener un iterator_tuple: Tuple[Iterator[A], Iterator[B]].
Esto puede hacerse en principio utilizando iterator_a, iterator_b = zip(*tuple_iterator).
Sin embargo, el * dentro de zip consume todo el tuple_iterator al principio y causa muchas operaciones.

Preferiría tener una tupla de iteradores, que no procesen los datos antes de que sean necesarios. Si consumo iterator_a primero, el código debería almacenar en caché los resultados de iterator_b hasta que consuma iterator_b. Sería aún más limpio y menos propenso a errores si también funciona al revés.

Información adicional: Entre el consumo de los elementos de iterator_a, quiero iniciar operaciones asíncronas.

¿Tienes alguna sugerencia?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Sí, en lugar de usar zip(*tuple_iterator), podrías definir una función generadora que devuelve los valores de iterator_a y iterator_b de forma perezosa, a medida que se solicitan. Aquí tienes un ejemplo de implementación:

    from typing import Iterator, Tuple
    
    def lazy_iterator_tuple(tuple_iterator: Iterator[Tuple[A, B]]) -> Tuple[Iterator[A], Iterator[B]]:
        def iterator_a():
            for a, _ in tuple_iterator:
                yield a
    
        def iterator_b():
            for _, b in tuple_iterator:
                yield b
    
        return iterator_a(), iterator_b()
    

    En esta implementación, iterator_a() e iterator_b() se definen como funciones generadoras que devuelven los elementos de A y B de forma perezosa, a medida que se solicitan. El tuple_iterator se consume una vez, y las dos funciones generadoras iteran sobre él de forma independiente para devolver sus valores respectivos.

    Usando esta función, puedes obtener una tupla de iteradores perezosos:

    iterator_a, iterator_b = lazy_iterator_tuple(tuple_iterator)
    

    Y luego puedes consumir iterator_a e iterator_b de forma independiente, solicitando los valores de forma perezosa según sea necesario:

    async def consume_iterator(iterator):
        async for item in iterator:
            # hacer algo con el elemento
            pass
    
    await consume_iterator(iterator_a)
    
    # comenzar las operaciones asíncronas aquí
    
    await consume_iterator(iterator_b)
    

    Ten en cuenta que necesitarías usar una función generadora asíncrona en lugar de una función generadora regular si deseas await operaciones asíncronas entre la consumición de elementos del iterador.

Comments are closed.