Aunque no lo sepas, probablemente ya utilices iterators en tu vida diaria como programador de Python. Un iterator es simplemente un objeto que cumple con los requisitos del Iteration Protocol (protocolo de iteración) y por lo tanto puede ser utilizado en ciclos. Por ejemplo,
for i inrange(10):print(i)
En este caso, la función range es un iterable que regresa un nuevo valor en cada ciclo. Para crear un objeto que sea un iterable, y por lo tanto, implemente el protocolo de iteración, debemos hacer tres cosas:
Crear una clase que implemente los métodos iter y next
iter debe regresar el objeto sobre el cual se iterará
next debe regresar el siguiente valor y aventar la excepción StopIteration cuando ya no hayan elementos sobre los cual iterar.
Por su parte, los generators son simplemente una forma rápida de crear iterables sin la necesidad de declarar una clase que implemente el protocolo de iteración. Para crear un generator simplemente declaramos una función y utilizamos el keyword yield en vez de return para regresar el siguiente valor en una iteración. Por ejemplo,
def fibonacci(max): a, b =0,1while a < max:yield a
a, b = b, a+b
Es importante recalcar que una vez que se ha agotado un generator ya no podemos utlizarlo y debemos crear una nueva instancia. Por ejemplo,
fib1 =fibonacci(20)fib_nums =[num for num in fib1]...double_fib_nums =[num *2for num in fib1] # no va a funcionar
double_fib_nums =[num *2for num infibonacci(30)] # sí funciona
Hola dejo mi aporte. espero que sea un poco mas legible y les sirva de ayuda.
#
def fibonacci(max): #max = max
print(max)print('') a, b =0,1while a < max:yield a
print(a)#el valor de retorno
a, b = b, a+b
fib1 =fibonacci(20)fib_nums =[num for num in fib1]print(fib_nums)#se muestra la lista generada
print('*'.center(50,'*'))double_fib_nums =[num *2for num in fib1] # no va a funcionar(no se muestra los valores de fib1), ya que fib1 se utilizo arriba
print(double_fib_nums)#se muestra una lista vacia por que ya no exiten los valores de fib1
double_fib_nums =[num *2for num infibonacci(30)] # sí funciona, ya que se vulve a llamar a fibonacci(x), un un leve cambio que n se multiplicara x 2print(double_fib_nums)#se muestran los valores recien generados #
print('')print('Ejemplos extra'.center(50,'-'))##ejemplos
# define a list
lista =[4,7,0,3]# get an iterator using iter()mi_iterador =iter(lista)#establecemos el objeto iterador
## iterate through it using next()#prints 4print(next(mi_iterador))#muestra el siguiente elemento de la lista
#prints 7print(next(mi_iterador))#muestra el siguiente elemento de la lista
## next(obj) is same as obj.__next__()#prints 0print(mi_iterador.__next__())#muestra el siguiente elemento de la lista
#prints 3print(mi_iterador.__next__())#muestra el siguiente elemento de la lista
## This will raise error, no items left
next(mi_iterador)#muestra error xq ya no hay elementos a mostrar
Iterator: Un objeto tipo iterator es un objeto que representa un flujo de datos, el cual puede ser recorrido en un proceso iterativo, como un bucle for, dentro de una función map o filter, en la creación de una list comprehension o generador, o en una comparación in.
Todo objeto iterator contiene implementado un método next() que es llamado en cada iteración devolviendo los sucesivos elementos del flujo de datos cada vez. El flujo de datos del objeto no tiene por qué estar guardado en memoria, sino que puede ser generado en tiempo real en cada iteración.
El objeto iterator guarda un estado interno para saber cuál fue el último elemento obtenido. Así, en la siguiente llamada a next(), se obtendrá el siguiente elemento correcto.
Cuando ya no quedan más elementos en el flujo de datos del iterator, la función next() lanza StopIteration. El estado interno no se reinicia automáticamente al llegar al final del flujo o al empezar a recorrerlo de nuevo. Es decir, sólo se puede recorrer una vez.
Además, tiene implementado el método iter() que devuelve el propio objeto iterator. Esto es necesario para poder implementar bucles con objetos iterator, como explicaremos después.
Perdon, alguien me puede explicar esta linea?
"fib_nums = [num for num in fib1]"
@thejb lo que observas en esa línea se denomina list comprehension y es una manera simplificada del lenguaje para crear los elementos de una lista sin necesidad de usar un ciclo. Te dejo el enlace de la clase correspondiente, que está más adelante en el curso: https://platzi.com/clases/1378-python-practico/14172-python-comprehensions/
el codigo con algunos print para ver el funcionamiento
def fibonacci(max):print(max) a, b =0,1while a < max:yield a
a, b = b, a+b
if __name__ =='__main__':print("inicio") fib1 =fibonacci(20) fib_nums =[num for num in fib1]print(fib_nums) double_fib_nums =[num *2for num in fib1] # no va a funcionar
print(double_fib_nums) double_fib_nums =[num *2for num infibonacci(30)] # sí funciona
print(double_fib_nums)print("fin")
Wooow, al analizar los ejemplos, hice esta comprobación:
>>>type(fib1)<class'generator'>
Interesante!!!
interesante :D
Hola, el codigo que aparece en el texto:
def fibonacci(max): a, b =0,1while a < max:yield a
a, b = b, a+b
Es equivalente a este que tal vez les puede ser mas claro para entender:
def fibonacci(max): a =0 b =1while a < max:yield a
aux = a
a = b
b = aux + b
yield lo que hace es ir regresando el valor de a cada vez que el código pasa por el, la sintaxis que usan en el código del articulo "a, b = b, a+b" es una manera de asignar valores a las variables pero mantenido el valor de las variables ahorrándote usar el aux que use en el otro código, ya que fibonacci requiere sumar los dos números anteriores para generar el siguiente, les recomiendo que si no saben como funciona la serie de fibonacci la investiguen y después lean de nuevo ambos códigos y entenderán como funcionan, si tiene alguna duda pueden preguntarme y con gusto contestare
Me podrían ayudar, dentro de Platzi, donde puedo ampliar el conocimiento sobre los temas de iteradores y generadores, muchas gracias.
No entiendo este punto a, b = 0, 1
Un poco confuso jejej
El Yield entonces es como una especie de return ? Digamos retorna el valor de donde fue invocada ? pero sigue la ejecucion
que es "finonacci" , O es solo un ejemplo?
Si, ahí faltó indicar mejor a qué refiere.
Lo explico-- Corresponde al cálculo de la sucesión de Fibonacci, que se define como una función F(n), donde F(0) = 0, F(1) = 1, y para cualquier otro valor N, se calcula F(N) = F(N-1) + F(N-2) (es decir, la suma de los valores anteriores calculados por la función)
# Clase 20 Iteradores y Generadores en Python: Creación y Uso Práctico
"""Iteradores y Generadores"""
for i in range(10):
print(i) # imprime el rango de 10 digitos R// 0 al 9
def fibonacci(max):
"""def funcion fibonacci"""
a, b = 0, 1 # a es cero y b es 1
while a < max: #esta es menor que < la flecha apuntando a la izquierda
yield a
a, b = b, a + b
# pero no esta definido como expresion unica a = 0
# sino que esta dentro de un def
print("=== Creando generador ===")
fib1 = fibonacci(20)
print("=== Primera lista ===")
fib_nums = [num for num in fib1]
print(fib_nums) # [0, 1, 1, 2, 3, 5, 8, 13]
print("=== Segunda lista (vacía) ===")
double_fib_nums = [num * 2 for num in fib1] # no va a funcionar
print(double_fib_nums)
# La secuencia de Fibonacci: cada número es la suma de los dos anteriores
# por ejemplo comienza en cero despues se va sumando en dos en dos
# 0 + 2 = 2// 2 + 2 = 4// 2 + 4 = 6 su resultado dara asi [0, 2, 2, 4, 6]
print("=== Nuevo generador 1 ===")
double_fib_nums = [num * 2 for num in fibonacci(5)]
print(double_fib_nums)
print("=== Nuevo generador 2 ===")
double_fib_nums1 = [num * 2 for num in fibonacci(30)] # similar a new generador 1
print(double_fib_nums1)
No me quedo muy claro el uso!
Te entiendo estoy igual pero solo es cuestion de repasarlo
Daniel, a lo que se refiere el profesor es que un iterator es simplemente un objeto que cumple ciertos requisitos y puede ser utilizado en ciclos.
Interesante...
Excelente. Cada generators es un iteratos, pero no al revés.
Gracias
Genial!, aprendí algo nuevo.
Alguien me ayuda a leer esta linea?
a, b = b, a+b
El resultado seria este?
a = b
b = a+b
En Python existe la assignation multiple, lo que corresponde a asignar valores a muchas variables en una sola linea de código, por eso, si tenemos:
a , b = 1 , 2
Lo que enverado estamos diciendo es: A la variable a le asignas el valor 1, y a la variable b le asignas el valor 2.
Entendemos entonces, que la variable se le asigna el valor en la posición que se encuentre la variable, y las posiciones las entendemos por la separación de comas.
>>> def fibonacci(max):... a, b=1,1...while a < max :...yield a
... a, b = b, a+b
...>>>fibonacci(20)<generator object fibonacci at 0x7f2d85c580f8>>>> im =fibonacci(20)>>> fib_nums =[num for num in im]>>> fib_nums
[1,1,2,3,5,8,13]>>> fib_nums =[num for num in im]>>> fib_nums
[] # tengo como respuesta un objeto vacio, pues una vez usado el generator se debe instanciar de nuevo.
Super! Aunque es raro ya no poder usar el generador!