重新考虑设计决策

Beginner

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

简介

在本节中,我们重新审视之前做出的一个设计决策。

这是一个实验(Guided Lab),提供逐步指导来帮助你学习和实践。请仔细按照说明完成每个步骤,获得实际操作经验。根据历史数据,这是一个 初级 级别的实验,完成率为 83%。获得了学习者 100% 的好评率。

文件名与可迭代对象

比较这两个返回相同输出的程序。

## 提供一个文件名
def read_data(filename):
    records = []
    with open(filename) as f:
        for line in f:
         ...
            records.append(r)
    return records

d = read_data('file.csv')
## 提供各行内容
def read_data(lines):
    records = []
    for line in lines:
     ...
        records.append(r)
    return records

with open('file.csv') as f:
    d = read_data(f)
  • 你更喜欢这两个函数中的哪一个?为什么?
  • 这两个函数中哪一个更灵活?

深度理解:“鸭子类型”

鸭子类型 是一种计算机编程概念,用于确定一个对象是否可用于特定目的。它是 鸭子测试 的一种应用。

如果它看起来像鸭子,游泳方式像鸭子,叫声也像鸭子,那么它很可能就是一只鸭子。

在上述 read_data() 的第二个版本中,该函数期望的是任何可迭代对象,而不仅仅是文件的各行。

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

这意味着我们可以将它用于其他的“行”。

## 一个 CSV 文件
lines = open('data.csv')
data = read_data(lines)

## 一个压缩文件
lines = gzip.open('data.csv.gz','rt')
data = read_data(lines)

## 标准输入
lines = sys.stdin
data = read_data(lines)

## 一个字符串列表
lines = ['ACME,50,91.1','IBM,75,123.45',... ]
data = read_data(lines)

这种设计具有相当大的灵活性。

问题:我们应该接受还是抵制这种灵活性?

库设计的最佳实践

代码库通常通过接受灵活性来更好地发挥作用。不要限制你的选择。强大的灵活性带来强大的能力。

练习 3.17:从文件名到类文件对象

你现在已经创建了一个名为 fileparse.py 的文件,其中包含一个函数 parse_csv()。该函数的工作方式如下:

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

目前,该函数期望传入一个文件名。然而,你可以让代码更灵活。修改该函数,使其能与任何类文件/可迭代对象一起工作。例如:

>>> 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])
>>>

在这段新代码中,如果你像之前那样传入一个文件名会发生什么?

>>> port = fileparse.parse_csv('portfolio.csv', types=[str,int,float])
>>> port
... 查看输出(应该会很奇怪)...
>>>

是的,你需要小心。你能添加一个安全检查来避免这种情况吗?

练习 3.18:修复现有函数

修复 report.py 文件中的 read_portfolio()read_prices() 函数,使其能与修改后的 parse_csv() 版本一起工作。这应该只涉及一个小修改。之后,你的 report.pypcost.py 程序应该能像以前一样正常工作。

总结

恭喜你!你已经完成了“设计讨论”实验。你可以在 LabEx 中练习更多实验来提升你的技能。