Rendimiento en Python Tutorial: Generator & Ejemplo de rendimiento versus retorno

¿Qué es el Python ¿producir?

La palabra clave de rendimiento en Python funciona como un retorno con el único

La diferencia es que en lugar de devolver un valor, devuelve un objeto generador al llamador.

Cuando se llama a una función y el hilo de ejecución encuentra una palabra clave yield en la función, la ejecución de la función se detiene en esa línea y devuelve un objeto generador al llamador.

Sintaxis

yield expression

Descripción

Python yield devuelve un objeto generador. GeneratorLas s son funciones especiales que deben iterarse para obtener los valores.

La palabra clave yield convierte la expresión dada en una función generadora que devuelve un objeto generador. Para obtener los valores del objeto, se debe iterar para leer los valores dados a yield.

Ejemplo: método de rendimiento

A continuación se muestra un ejemplo sencillo de rendimiento. La función testyield() tiene una palabra clave de rendimiento con la cadena "Bienvenido a Guru99 Python Tutoriales“. Cuando se llama a la función, se imprime la salida y proporciona un objeto generador en lugar del valor real.

def testyield():
  yield "Welcome to Guru99 Python Tutorials"
output = testyield()
print(output)

Salida:

<generator object testyield at 0x00000028265EB9A8>

La salida dada es un objeto generador, que tiene el valor que le hemos dado a yield.

¡Pero no estamos entendiendo el mensaje que tenemos que dar para producir resultados!

Para imprimir el mensaje entregado a yield tendremos que iterar el objeto generador como se muestra en el siguiente ejemplo:

def testyield():
  yield "Welcome to Guru99 Python Tutorials"

output = testyield()
for i in output:
    print(i)

Salida:

Welcome to Guru99 Python Tutorials

¿Qué son Generators en Python?

GeneratorLas funciones s son funciones que devuelven un objeto generador iterable. Los valores del objeto generador se obtienen de a uno por vez en lugar de la lista completa en conjunto y, por lo tanto, para obtener los valores reales, puede utilizar un bucle for, utilizando el método next() o list().

Gracias a Generator función

Puede crear generadores utilizando la función de generador y la expresión de generador.

Una función generadora es como una función normal, en lugar de tener un valor de retorno, tendrá una palabra clave yield.

Para crear una función generadora, deberá agregar una palabra clave yield. Los siguientes ejemplos muestran cómo crear una función generadora.

def generator():
    yield "H"
    yield "E"
    yield "L"
    yield "L"
    yield "O"

test = generator()
for i in test:
    print(i)

Salida:

H
E
L
L
O

Diferencia entre función normal v/s Generator función.

Entendamos en qué se diferencia una función generadora de una función normal.

Hay 2 funciones normal_test() y generator_test().

Se supone que ambas funciones deben devolver la cadena “Hola mundo”. La función normal_test() utiliza return y la función generator_test() utiliza yield.

# Normal function
def normal_test():
    return "Hello World"
	
#Generator function
def generator_test():
	yield "Hello World"
print(normal_test()) #call to normal function
print(generator_test()) # call to generator function

Salida:

Hello World
<generator object generator_test at 0x00000012F2F5BA20>

El resultado muestra que cuando se llama a la función normal normal_test(), devuelve la cadena Hola mundo. Para una función generadora con la palabra clave yield, devuelve y no la cuerda.

Esta es la principal diferencia entre una función generadora y una función normal. Ahora, para obtener el valor del objeto generador, debemos utilizar el objeto dentro del bucle for o utilizar el método next() o hacer uso de list().

print(next(generator_test()))  # will output Hello World

Una diferencia más para agregar entre la función normal y la función generadora es que cuando llamas a una función normal, la ejecución comenzará y se detendrá cuando llegue a volvemos y el valor se devuelve a la persona que llama. Entonces, cuando comienza la ejecución, no puede detener la función normal en el medio y solo se detendrá cuando encuentre la palabra clave return.

Pero en el caso de la función generadora, una vez que comienza la ejecución, cuando obtiene el primer rendimiento, detiene la ejecución y devuelve el objeto generador. Puede usar el objeto generador para obtener los valores y también pausar y reanudar según sus necesidades.

¿Cómo leer los valores del generador?

Puede leer los valores de un objeto generador utilizando una lista(), un bucle for y el método next().

Usando: lista()

Una lista es un objeto iterable que tiene sus elementos dentro de corchetes. El uso de list() en un objeto generador proporcionará todos los valores que contiene el generador.

def even_numbers(n):
    for x in range(n):
       if (x%2==0): 
           yield x       
num = even_numbers(10)
print(list(num))

Salida:

[0, 2, 4, 6, 8]

Usando: para-en

En el ejemplo, hay una función definida even_numbers() que te proporcionará todos los números pares para el n definido. La llamada a la función even_numbers() devolverá un objeto generador, que se utiliza dentro del bucle for.

Ejemplo:

def even_numbers(n):
    for x in range(n):
       if (x%2==0): 
           yield x       
num = even_numbers(10)
for i in num:
    print(i)

Salida:

0
2
4
6
8

Usando siguiente()

El método next() le proporcionará el siguiente elemento de la lista, matriz u objeto. Una vez que la lista esté vacía, y si se llama a next(), devolverá un error con la señal stopIteration. Este error, de next() indica que no hay más elementos en la lista.

def even_numbers(n):
    for x in range(n):
       if (x%2==0): 
           yield x       
num = even_numbers(10)
print(next(num))
print(next(num))
print(next(num))
print(next(num))
print(next(num))
print(next(num))

Salida:

0
2
4
6
8
Traceback (most recent call last):
  File "main.py", line 11, in <module>
    print(next(num))
StopIteration

Generators son de uso único

En el caso de los generadores, estos solo están disponibles para su uso una vez. Si intentas usarlos nuevamente, estarán vacíos.

Por ejemplo:

def even_numbers(n):
    for x in range(n):
       if (x%2==0): 
           yield x       
num = even_numbers(10)
for i in num:
    print(i)

print("\n")
print("Calling the generator again: ", list(num))

Salida:

0
2
4
6
8
Calling the generator again:  []

En caso de querer que se vuelva a utilizar la salida, tendrás que realizar la llamada para volver a funcionar.

Ejemplo: Generatorsy rendimiento para series de Fibonacci

El siguiente ejemplo muestra cómo utilizar generadores y rendimiento en Python. El ejemplo generará la serie de Fibonacci.

def getFibonnaciSeries(num):
    c1, c2 = 0, 1
    count = 0
    while count < num:
        yield c1
        c3 = c1 + c2
        c1 = c2
        c2 = c3
        count += 1
fin = getFibonnaciSeries(7)
print(fin)
for i in fin:
    print(i)

Salida:

<generator object getFibonnaciSeries at 0x0000007F39C8BA20>
0
1
1
2
3
5
8

Ejemplo: llamada a función con rendimiento

En este ejemplo veremos cómo llamar a una función con rendimiento.

El siguiente ejemplo tiene una función llamada prueba() que devuelve el cuadrado del número dado. Hay otra función llamada getSquare() que usa test() con la palabra clave de rendimiento. El resultado proporciona el valor cuadrado para un rango de números determinado.

def test(n):
    return n*n

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

sq = getSquare(10)
for i in sq:
    print(i)

Salida:

0
1
4
9
16
25
36
49
64
81

Cuándo utilizar rendimiento en lugar de retorno en Python

Python3 rendimiento La palabra clave devuelve un generador al llamador y la ejecución del código comienza solo cuando se itera el generador.

A volvemos en una función es el final de la ejecución de la función y se devuelve un único valor a la persona que llama.

Aquí está la situación en la que deberías usar Yield en lugar de Return

  • Utilice rendimiento en lugar de retorno cuando el tamaño de los datos sea grande
  • El rendimiento es la mejor opción cuando necesita que su ejecución sea más rápida en grandes conjuntos de datos
  • Utilice rendimiento cuando desee devolver un gran conjunto de valores a la función de llamada
  • El rendimiento es una forma eficiente de producir datos grandes o infinitos.

Rendimiento versus retorno

Aquí están las diferencias entre rendimiento y retorno.

Rendimiento Ida y vuelta
Yield devuelve un objeto generador al llamador, y la ejecución del código comienza solo cuando se itera el generador. Un retorno en una función es el final de la ejecución de la función y se devuelve un único valor a la persona que llama.
Cuando se llama a la función y encuentra la palabra clave yield, la ejecución de la función se detiene. Devuelve el objeto generador al invocador. La ejecución de la función comenzará solo cuando se ejecute el objeto generador. Cuando se llama a la función, la ejecución comienza y el valor se devuelve a la persona que llama si hay una palabra clave de retorno. El retorno dentro de la función marca el final de la ejecución de la función.
expresión de rendimiento expresión de retorno
No se utiliza memoria cuando se utiliza la palabra clave de rendimiento. La memoria se asigna para el valor devuelto.
Muy útil si tiene que lidiar con datos de gran tamaño ya que no se utiliza la memoria. Conveniente para tamaños de datos muy pequeños.
El rendimiento es mejor si se utiliza la palabra clave de rendimiento para datos de gran tamaño. Se utiliza mucha memoria si el tamaño de los datos es enorme, lo que obstaculizará el rendimiento.
El tiempo de ejecución es más rápido en caso de rendimiento para datos de gran tamaño. El tiempo de ejecución utilizado es mayor ya que se realiza un procesamiento adicional en caso de que el tamaño de sus datos sea enorme, funcionará bien para tamaños de datos pequeños.

Resum

  • La palabra clave yield en Python funciona como un retorno con la única diferencia de que en lugar de devolver un valor, devuelve una función generadora al llamador.
  • Un generador es un tipo especial de iterador que, una vez utilizado, no estará disponible nuevamente. Los valores no se almacenan en la memoria y solo están disponibles cuando se los llama.
  • Los valores del generador se pueden leer utilizando los métodos for-in, list() y next().
  • La principal diferencia entre yield y return es que yield devuelve una función generadora al llamador y return le da un valor único al llamador.
  • Yield no almacena ninguno de los valores en la memoria y la ventaja es que resulta útil cuando el tamaño de los datos es grande, ya que ninguno de los valores se almacena en la memoria.
  • El rendimiento es mejor si se utiliza la palabra clave de rendimiento en comparación con el retorno de datos de gran tamaño.