Contents|上一节(3.5主模块)|下一节(4类)3.6设计讨论在本节中,我们将重新考虑之前做出的设计决策。文件名与Iterables考虑以下两个返回相同输出的程序。#提供文件名defread_data(filename):records=[]withopen(filename)asf:forlineinf:...records.append(r)returnrecordsd=read_data('file.csv')#Providelinesdefread_data(lines):records=[]forlineinlines:...records.append(r)returnrecordswithopen('file.csv')asf:d=read_data(f)你喜欢使用哪个函数?为什么?哪个函数更灵活?DuckTyping在计算机编程中,DuckTyping用于确定对象是否可用于特定目的。这是鸭子测试的一个应用。如果它长得像鸭子,游起来像鸭子,叫声也像鸭子,那么它很可能就是鸭子。上面的第二个read_data()函数接受任何可迭代的,而不仅仅是文件行。defread_data(lines):records=[]forlineinlines:...records.append(r)返回记录,这意味着我们可以用它来处理其他行。#CSV文件lines=open('data.csv')data=read_data(lines)#压缩文件lines=gzip.open('data.csv.gz','rt')data=read_data(lines)#标准输入行=sys.stdindata=read_data(lines)#Alistofstringslines=['ACME,50,91.1','IBM,75,123.45',...]data=read_data(lines)这种设计具有很大的灵活性。问题:我们应该接受还是反对这种灵活性?库设计最佳实践通常,通过拥抱灵活性可以更好地服务于代码库。不要限制您的选择,极大的灵活性带来强大的力量。练习练习3.17:从文件名到类文件对象您现在已经创建了一个包含parse_csv()函数的fileparse.py文件。parse_csv()函数是这样工作的:>>>importfileparse>>>portfolio=fileparse.parse_csv('Data/portfolio.csv',types=[str,int,float])>>>虽然函数接受一个The然而,filename允许您使代码更加灵活。请求修改函数,使其可以接受任何类文件或可迭代对象。例如:>>>importfileparse>>>importgzip>>>withgzip.open('Data/portfolio.csv.gz','rt')asfile:...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...看输出(应该是疯了)...>>>as如上面的代码所示,这可能会产生意想不到的结果,因此在修改时需要小心。您可以添加安全检查来避免这种情况吗?练习3.18:修复现有函数请修复report.py文件中的read_portfolio()和read_prices()函数。以便他们可以使用修改后的parse_csv()函数。这应该只涉及较小的修改。之后,report.py和pcost.py程序应该像以前一样工作。目录|上一节(3.5主模块)|下一节(4类)注意:参见https://github.com/codists/pr...
