目录 | 上一节 (3.5 主模块) | [下一节 (4 类)]()

3.6 设计探讨

本节,咱们重新考虑之前所做的设计决策。

文件名与可迭代对象

思考以下两个返回雷同输入的程序。

# Provide a filenamedef read_data(filename):    records = []    with open(filename) as f:        for line in f:            ...            records.append(r)    return recordsd = read_data('file.csv')
# Provide linesdef read_data(lines):    records = []    for line in lines:        ...        records.append(r)    return recordswith open('file.csv') as f:    d = read_data(f)
  • 你更偏向于应用哪个函数?为什么?
  • 哪个函数更灵便?

鸭子类型(Duck Typing)

在计算机程序设计中,鸭子类型 用于确定一个对象是否可用于特定目标。这是 鸭子测试 的一种利用。

如果它看起来像鸭子、游泳像鸭子、叫声像鸭子,那么它可能就是只鸭子。

上述第二个 read_data() 函数承受任何可迭代对象,而不仅是文件行。

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

这意味着咱们能够应用它解决其它的行(lines)

# A CSV filelines = open('data.csv')data = read_data(lines)# A zipped filelines = gzip.open('data.csv.gz','rt')data = read_data(lines)# The Standard Inputlines = sys.stdindata = read_data(lines)# A list of stringslines = ['ACME,50,91.1','IBM,75,123.45', ... ]data = read_data(lines)

这种设计具备很大的灵活性。

问题:咱们应该拥抱还是拥护这种灵活性?

库设计最佳实际

通常,拥抱灵活性能够更好的服务于代码库。不要限度你的抉择,灵活性大,带来的威力也大。

练习

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

当初,你曾经创立了一个蕴含 parse_csv() 函数的 fileparse.py 文件。parse_csv() 函数像上面这样工作:

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

尽管函数承受的是一个文件名,然而,你能够使代码更具灵活性。申请批改函数,以便它能够承受任何类文件或者可迭代对象。例如:

>>> import fileparse>>> import gzip>>> with gzip.open('Data/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('Data/portfolio.csv', types=[str,int,float])>>> port... look at output (it should be crazy) ...>>>

正如下面代码显示的那样,这可能带来意想不到的后果,所以,批改的时候须要小心一些。你能够增加安全检查来防止这种状况吗?

练习 3.18:修复(fix)现有函数

请修复 report.py 文件中的 read_portfolio()read_prices() 函数。以便它们能够应用批改后的 parse_csv() 函数。这应该只波及较小的批改。之后,report.pypcost.py 程序应可能像以往一样工作。

目录 | 上一节 (3.5 主模块) | [下一节 (4 类)]()

注:残缺翻译见 https://github.com/codists/pr...