Reconsiderar la Decisión de Diseño

PythonPythonBeginner
Practicar Ahora

This tutorial is from open-source community. Access the source code

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

En esta sección reconsideramos una decisión de diseño tomada anteriormente.

Nombres de archivos versus Iterables

Compara estos dos programas que devuelven la misma salida.

## Proporciona un nombre de archivo
def read_data(filename):
    records = []
    with open(filename) as f:
        for line in f:
         ...
            records.append(r)
    return records

d = read_data('file.csv')
## Proporciona líneas
def read_data(lines):
    records = []
    for line in lines:
     ...
        records.append(r)
    return records

with open('file.csv') as f:
    d = read_data(f)
  • ¿Cuál de estas funciones prefieres? ¿Por qué?
  • ¿Cuál de estas funciones es más flexible?

Idea Profunda: "Duck Typing"

Duck Typing es un concepto de programación informática para determinar si un objeto puede ser utilizado con un propósito particular. Es una aplicación de la prueba del pato.

Si parece un pato, nada como un pato y cuac como un pato, entonces probablemente es un pato.

En la segunda versión de read_data() arriba, la función espera cualquier objeto iterable. No solo las líneas de un archivo.

def read_data(lines):
    records = []
    for line in lines:
     ...
        records.append(r)
    return records

Esto significa que podemos utilizarlo con otras líneas.

## Un archivo CSV
lines = open('data.csv')
data = read_data(lines)

## Un archivo comprimido
lines = gzip.open('data.csv.gz','rt')
data = read_data(lines)

## La Entrada Estándar
lines = sys.stdin
data = read_data(lines)

## Una lista de cadenas
lines = ['ACME,50,91.1','IBM,75,123.45',...]
data = read_data(lines)

Hay una gran flexibilidad con este diseño.

Pregunta: ¿Debemos aceptar o combatir esta flexibilidad?

Mejores Prácticas en el Diseño de Bibliotecas

A menudo, las bibliotecas de código se benefician más al abrazar la flexibilidad. No restringas tus opciones. Con gran flexibilidad viene gran poder.

Ejercicio 3.17: De nombres de archivos a objetos similares a archivos

Ahora has creado un archivo fileparse.py que contiene una función parse_csv(). La función funcionaba así:

>>> import fileparse
>>> portfolio = fileparse.parse_csv('portfolio.csv', types=[str,int,float])
>>>

En este momento, la función espera recibir un nombre de archivo. Sin embargo, puedes hacer que el código sea más flexible. Modifica la función para que funcione con cualquier objeto similar a un archivo/iterable. Por ejemplo:

>>> import fileparse
>>> import gzip
>>> with gzip.open('portfolio.csv.gz', 'rt') as file:
...      port = fileparse.parse_csv(file, types=[str,int,float])
...
>>> lines = ['name,shares,price', 'AA,100,34.23', 'IBM,50,91.1', 'HPE,75,45.1']
>>> port = fileparse.parse_csv(lines, types=[str,int,float])
>>>

En este nuevo código, ¿qué pasa si pasas un nombre de archivo como antes?

>>> port = fileparse.parse_csv('portfolio.csv', types=[str,int,float])
>>> port
... mira la salida (debería ser un caos)...
>>>

Sí, tendrás que tener cuidado. ¿Podrías agregar una comprobación de seguridad para evitar esto?

✨ Revisar Solución y Practicar

Ejercicio 3.18: Corrigiendo funciones existentes

Corrige las funciones read_portfolio() y read_prices() en el archivo report.py para que funcionen con la versión modificada de parse_csv(). Esto solo debería implicar una modificación mínima. Después de eso, tus programas report.py y pcost.py deberían funcionar de la misma manera que siempre lo han hecho.

✨ Revisar Solución y Practicar

Resumen

¡Felicitaciones! Has completado el laboratorio de Discusión de Diseño. Puedes practicar más laboratorios en LabEx para mejorar tus habilidades.