Apuntes_Python/02_conceptos/14_generators/README.md
2022-12-24 22:41:20 -03:00

3.0 KiB

Generadores

Son funciones especiales, devuelven una secuencia de varoles, de uno, por cada llamada.

Son una forma sencilla y potente de iterador. Un iterador tiene siempre sus elementos disponibles,
un generador los va GENERANDO con un llamado al metodo __next()__ .

Con esto se pueden tener generadores, que generen infitinos elementos (ej. nums. naturares).

Retornan un resultado con la sentencia "yield". Y la funcion queda en espera, hasta que es
invocada nuevamente.

Son funciones que devuelven un objeto iterable.
Son mas eficientes en uso de memoria, generando los items uno a la vez.

Ejemplos:


Creación

def mi_generador():
    yield 1
    yield 2
    yield 3

g = mi_generador()

for i in g:
    print(i)
#   1
#   2
#   3


g2 = mi_generador()

print(next(g2))
#   1

print(next(g2))
#   2

También se pueden crear similiar al metodo de comprensión de listas,
usando () en vez de [].

mi_generador = (i for i in range(10) if i % 2 == 0)

migenerador3 = (i for i in range(1000000) if i % 2 == 0)

#for i in migenerador3:
#    print(i)
#print(list(migenerador3))
# 0 2 4 6 8

milista = [i for i in range(1000000) if i % 2 == 0]

print(sys.getsizeof(milista))
# 4,1 MB

print(sys.getsizeof(migenerador3))
# 112 B

Valores fuera de rango

Causan una excepcion StopIteration

g3 = mi_generador()
print(sum(g3))
#   6

def mi_generador2():
    yield 5
    yield 2
    yield 4

g = mi_generador2()
print(sorted(g))
#   [2, 4, 5]


def cuenta_regres(num):
    print('Iniciando')
    while num > 0:
        yield num
        num -= 1

cr = cuenta_regres(4)
print(next(cr))
print(next(cr))

Ejemplo de uso, para ahorro de memoria

import sys

def primer_n(n):
    nums = []
    num = 0
    while num < n:
        nums.append(num)
        num += 1
    return nums

# Función ocupa 8,3 MB de memoria
# print(sys.getsizeof(primer_n(1000000)))

print(primer_n(10))
#   [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]


def primer_n_gen(n):
    num = 0
    while num < n:
        yield num
        num += 1

# Función ocupa 112 KB de memoria
# print(sys.getsizeof(primer_n_gen(1000000)))

print(primer_n(10))
#   [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Ejemplo secuencia fibonacci

def fibonacci(limite):
    "0, 1, 1, 2, 3, 5, 8, 13..."
    a, b = 0, 1
    while a < limite:
        yield a
        a, b = b, a + b

fibo = fibonacci(300)
for i in fibo:
    print(i, end=" ")
print("")