Traducción: "Programación práctica en Python" 06_02_Customizing_iteration

Índice | Sección anterior (6.1 Protocolo de iteración) | Sección siguiente (6.3 Productor / Consumidor)

6.2 iteración personalizada

Sitio web de reembolsos www.cpa5.cn

Esta sección explora cómo personalizar iteraciones usando funciones de generador.

problema

Suponga que desea personalizar el modo de iteración.

Por ejemplo: Countdown:

>>> for x in countdown(10):
...   print(x, end=' ')
...
10 9 8 7 6 5 4 3 2 1
>>>

Hay una forma sencilla de hacer esto.

Constructor

Un generador es una función que define la iteración:

def countdown(n):
    while n > 0:
        yield n
        n -= 1

Ejemplo:

>>> for x in countdown(10):
...   print(x, end=' ')
...
10 9 8 7 6 5 4 3 2 1
>>>

Cualquier uso de una yielddeclaración de función conocida como generador.

El comportamiento de las funciones generadoras es diferente al de las funciones ordinarias. Llamar a una función generadora crea un objeto generador en lugar de ejecutar la función inmediatamente:

def countdown(n):
    # Added a print statement
    print('Counting down from', n)
    while n > 0:
        yield n
        n -= 1
>>> x = countdown(10)
# There is NO PRINT STATEMENT
>>> x
# x is a generator object
<generator object at 0x58490>
>>>

La función de generador solo se __next__()ejecuta cuando se llama al método:

>>> x = countdown(10)
>>> x
<generator object at 0x58490>
>>> x.__next__()
Counting down from 10
10
>>>

yieldSe genera un valor, pero se ejecuta la función de suspensión. Función de constructor en la siguiente llamada para __next__()reanudar cuando el método (reanudar),

>>> x.__next__()
9
>>> x.__next__()
8

Cuando el generador devuelve el último valor, la iteración de nuevo provocará un error.

>>> x.__next__()
1
>>> x.__next__()
Traceback (most recent call last):
File "<stdin>", line 1, in ? StopIteration
>>>

Observación: El protocolo implementado por la función de generador es el mismo que el protocolo subyacente usado por la instrucción for en listas, tuplas, diccionarios y archivos.

Ejercicio

Ejercicio 6.4: Un generador simple

Si desea una iteración personalizada, siempre debe considerar las funciones del generador. La función del generador es fácil de escribir: cree una función necesaria para realizar la lógica iterativa y utilice el yieldvalor de transmisión.

Por ejemplo, para crear un generador que encuentre subcadenas coincidentes en cada línea de un archivo:

>>> def filematch(filename, substr):
        with open(filename, 'r') as f:
            for line in f:
                if substr in line:
                    yield line

>>> for line in open('Data/portfolio.csv'):
        print(line, end='')

name,shares,price
"AA",100,32.20
"IBM",50,91.10
"CAT",150,83.44
"MSFT",200,51.23
"GE",95,40.37
"MSFT",50,65.10
"IBM",100,70.44
>>> for line in filematch('Data/portfolio.csv', 'IBM'):
        print(line, end='')

"IBM",50,91.10
"IBM",100,70.44
>>>

Esta es una idea interesante: puede ocultar el procesamiento personalizado en una función y aplicar la función a un bucle for. El siguiente ejemplo explora una situación más inusual.

Ejercicio 6.5: Supervisar fuentes de datos de transmisión

El generador se puede utilizar para monitorear fuentes de datos en tiempo real (como archivos de registro, noticias del mercado de valores). En esta parte, exploraremos la idea de "usar generadores para monitorear fuentes de datos en tiempo real". Primero, siga estrictamente las instrucciones a continuación.

Data/stocksim.pyPara imitar los datos del mercado de valores, se seguirán escribiendo datos en tiempo real en el Data/stocklog.csvarchivo. Abra una ventana de línea de comando separada, ingrese al Data/directorio y luego ejecute el stocksim.pyprograma:

bash % python3 stocksim.py

Si está utilizando un sistema Windows, busque el stocksim.pyarchivo y luego haga doble clic en el archivo para ejecutarlo. Entonces, dejemos eso a un lado para el programa (se ha estado ejecutando en eso), abra otra ventana de línea de comandos, vea que el programa de simulación está (traducción :) stocksim.pyescribiendo un Data/stocklog.csvarchivo de datos (traducción: si está usando un sistema Linux, puede, vaya al directorio de datos y luego use el tail -f stocklog.csvcomando para ver). Debería ver una nueva línea de texto que se agrega al Data/stocklog.csvarchivo cada pocos segundos . De manera similar, deje que el programa se ejecute en segundo plano; el programa se ejecutará durante unas horas (no se preocupe por esto).

stocksim.pyDespués de ejecutar el programa, escribamos un programa para abrir Data/stocklog.csvel archivo, movernos al final del archivo y ver la nueva salida. Cree el follow.pyarchivo de directorio en el trabajo y coloque el siguiente código en el que:

# follow.py
import os
import time

f = open('Data/stocklog.csv')
f.seek(0, os.SEEK_END)   # Move file pointer 0 bytes from end of file

while True:
    line = f.readline()
    if line == '':
        time.sleep(0.1)   # Sleep briefly and retry
        continue
    fields = line.split(',')
    name = fields[0].strip('"')
    price = float(fields[1])
    change = float(fields[4])
    if change < 0:
        print(f'{name:>10s} {price:>10.2f} {change:>10.2f}')

Ejecute el follow.py programa, verá cotizaciones de acciones en tiempo real (ticker de acciones). follow.py El código en un sistema similar a Unix para ver el tail -fcomando del archivo de registro .

Nota: En este ejemplo, los readline()métodos de uso y generalmente leen de un archivo con una realización ligeramente diferente (generalmente forcircular). En este caso, usamos readline()el final para detectar archivos duplicados, para ver si se agregan nuevos datos (el readline()método devuelve los nuevos datos o una cadena vacía).

Ejercicio 6.6: use generadores para generar datos

Ver el código del Ejercicio 6.5 encontrará que la primera parte del código para generar algunas líneas de datos, mientras que la whilecirculación al final de la declaración de datos de consumo. Una de las principales características de los generadores es que puede mover el código que genera datos a funciones reutilizables.

6.5 Edite el código de práctica, para que a través de la función de generador se follow(filename)lea el archivo de ejecución. Implemente los cambios para que funcione el siguiente código:

>>> for line in follow('Data/stocklog.csv'):
          print(line, end='')

... Should see lines of output produced here ...

Modifique el código de cotización de acciones para que el código tenga el siguiente aspecto:

if __name__ == '__main__':
    for line in follow('Data/stocklog.csv'):
        fields = line.split(',')
        name = fields[0].strip('"')
        price = float(fields[1])
        change = float(fields[4])
        if change < 0:
            print(f'{name:>10s} {price:>10.2f} {change:>10.2f}')

Ejercicio 6.7: Ver cartera de acciones

Modifique el follow.pyprograma para que el programa pueda ver la transmisión de datos de acciones e imprimir la información de la cartera de acciones en esas acciones. Ejemplo:

if __name__ == '__main__':
    import report

    portfolio = report.read_portfolio('Data/portfolio.csv')

    for line in follow('Data/stocklog.csv'):
        fields = line.split(',')
        name = fields[0].strip('"')
        price = float(fields[1])
        change = float(fields[4])
        if name in portfolio:
            print(f'{name:>10s} {price:>10.2f} {change:>10.2f}')

Nota: Para poder ejecutar este código, Portfoliola clase debe ser compatible con el inoperador. Consulte el ejercicio 6.3 para asegurarse de que la Portfolioclase implemente el __contains__()operador.

discutir

Aquí, mueve un patrón iterativo interesante (líneas de lectura al final del archivo) a la función. follow()Las funciones son ahora utilidades completamente universales que se pueden utilizar en cualquier programa. Por ejemplo, puede utilizar la follow()función para ver el registro del servidor, el registro de depuración, similar a otras fuentes de datos.

Índice | Sección anterior (6.1 Protocolo de iteración) | Sección siguiente (6.3 Productor / Consumidor)

Nota: consulte https://github.com/codists/practical-python-zh para obtener la traducción completa

Supongo que te gusta

Origin blog.csdn.net/weixin_48967543/article/details/114924464
Recomendado
Clasificación