¿No sé cómo aprender Python con rendimiento?
La secuencia de Fibonacci es una secuencia recursiva muy simple. Cualquier número excepto el primero y el segundo se puede obtener sumando los dos primeros números. Es un problema muy simple utilizar un programa de computadora para generar los primeros n números de la secuencia de Fibonacci. Algunos socios basados en Python pueden escribir fácilmente la siguiente función:
Versión 1: simplemente genera los primeros n números de la secuencia de Fibonacci.
Al ejecutar el código anterior, podemos obtener el siguiente resultado:
No hay ningún problema con el resultado de salida, pero el método de escritura de la versión 1 es imprimir el número directamente en la función createNum, que hará que esta función La reutilización sea pobre porque la función createNum devuelve Ninguno y otras funciones no pueden obtener la secuencia generada por esta función.
Para mejorar la reutilización de la función createNum, es mejor no imprimir la serie directamente, sino devolver una lista. La siguiente es la segunda versión reescrita de la función createNum:
Versión 2: genera los primeros n números de la secuencia de Fibonacci
La lista de resultados devuelta por la función createNum en esta versión es de la siguiente manera:
La función createNum reescrita puede cumplir con los requisitos de reutilización al devolver una lista vinculada, pero al mismo tiempo hay un problema obvio: la memoria ocupada por la función aumentará a medida que aumente el número de parámetros. . Si desea controlar el uso de la memoria, es mejor no utilizar una lista vinculada para guardar resultados intermedios, sino utilizar objetos iterables para iterar. Devuelve el siguiente valor en cada iteración para que el espacio de memoria sea muy pequeño. Porque devuelve un objeto iterable directamente.
Versión 3: use rendimiento para generar los primeros n números de la secuencia de Fibonacci
También puede llamar manualmente al método next() de createNum(5) (porque createNum(5) es un objeto generador con un método next()), para que podamos ver el proceso de ejecución de createNum más claramente:
Versión 4: Proceso de ejecución
Ejecute el código anterior, El El resultado es el siguiente:
Se puede encontrar en el resultado que se genera una excepción StopIteration al ejecutar la sexta impresión (next(num)) porque la función ya se ejecutó cuando se realizó la quinta impresión (next( num)) se ejecuta al final, al ejecutar la sexta impresión (next(num)), el generador arroja automáticamente una excepción StopIteration, indicando que la iteración se ha completado. En el bucle for, no es necesario manejar la excepción StopIteration, el bucle finalizará normalmente.
En pocas palabras, la función de rendimiento es convertir una función en un generador. La función con rendimiento ya no es una función ordinaria, el intérprete de Python la tratará como un generador. Llamar a createNum(5) no ejecutará la función createNum, ¡pero devolverá un objeto iterable!
Al ejecutar un bucle for, el código dentro de la función createNum se ejecutará en cada bucle. Cuando se ejecuta la función createNum para producir b, devuelve un valor iterable. En la siguiente iteración, el código continuará ejecutándose a partir de la siguiente declaración de rendimiento b, y las variables locales de la función tendrán exactamente el mismo aspecto que antes de la última interrupción, por lo que la función continuará ejecutándose hasta que se alcance nuevamente el rendimiento.
Una función de rendimiento es un generador, que es diferente de una función ordinaria. Generar un generador parece una llamada de función, pero no ejecuta ningún código de función hasta que se llama a next() (que se llama automáticamente en un bucle for). Aunque el flujo de ejecución todavía se ejecuta de acuerdo con el flujo de la función, cada vez que se ejecuta una declaración de rendimiento, se interrumpirá y se devolverá un valor de iteración, y la ejecución continuará desde la siguiente declaración de rendimiento en la siguiente ejecución.
Parece que una función es interrumpida varias veces por el rendimiento durante la ejecución normal, y cada interrupción devuelve el valor de iteración actual a través del rendimiento.
Los beneficios del rendimiento son obvios. Si anula una función como generador, obtiene la capacidad de iterar. En comparación con guardar el estado de una clase para calcular el valor de next (), el código es conciso y el proceso de ejecución es extremadamente claro.