本节讨论列表(list),字典(dict)和集合(set)。
概述通常,程序必须处理许多对象。
股票的投资组合
股票价格表
这里有三种主要的选择(译注:数据结构)可以使用:
列表。有序的数据。
字典。无序的数据。
集合。互异且无序的数据。
把列表当作容器当数据顺序很重要时,请使用列表。记住,列表可以存储任何类型的对象。例如,包含元组的列表:
portfolio = [ ('GOOG', 100, 490.1), ('IBM', 50, 91.3), ('CAT', 150, 83.44) ] portfolio[0] # ('GOOG', 100, 490.1) portfolio[2] # ('CAT', 150, 83.44) 列表构建从零开始构建列表。
records = [] # Initial empty list # Use .append() to add more items records.append(('GOOG', 100, 490.10)) records.append(('IBM', 50, 91.3)) ...从文件读取记录的示例:
records = [] # Initial empty list with open('Data/portfolio.csv', 'rt') as f: next(f) # Skip header for line in f: row = line.split(',') records.append((row[0], int(row[1]), float(row[2]))) 把字典当作容器如果要快速随机查找(通过键名),那么字典很有用。例如,股票价格字典:
prices = { 'GOOG': 513.25, 'CAT': 87.22, 'IBM': 93.37, 'MSFT': 44.12 }以下是一些简单的查找:
>>> prices['IBM'] 93.37 >>> prices['GOOG'] 513.25 >>> 字典构建从零开始构建字典的示例:
prices = {} # Initial empty dict # Insert new items prices['GOOG'] = 513.25 prices['CAT'] = 87.22 prices['IBM'] = 93.37从文件内容填充字典的示例:
prices = {} # Initial empty dict with open('Data/prices.csv', 'rt') as f: for line in f: row = line.split(',') prices[row[0]] = float(row[1])注意:如果是在 Data/prices.csv 文件上尝试此操作,会发现几乎可以正常工作——但是,在末尾有一个空行导致程序崩溃了。需要找出一些方法来修改代码以解决此问题(参见练习 2.6)。
字典查找测试键是否存在:
if key in d: # YES else: # NO可以查找可能不存在的值,并在值不存在的情况下提供默认值。
name = d.get(key, default)示例:
>>> prices.get('IBM', 0.0) 93.37 >>> prices.get('SCOX', 0.0) 0.0 >>> 组合键在 Python 中,几乎任何类型的值都可以用作字典的键。字典的键必须是不可变类型。例如,元组:
holidays = { (1, 1) : 'New Years', (3, 14) : 'Pi day', (9, 13) : "Programmer's day", }然后访问:
>>> holidays[3, 14] 'Pi day' >>>列表,集合或者其它字典都不能用作字典的键,因为列表和字典(译注:集合也是使用哈希技术实现的)是可变的。
集合集合是互异且无序的数据。
tech_stocks = { 'IBM','AAPL','MSFT' } # Alternative syntax tech_stocks = set(['IBM', 'AAPL', 'MSFT'])集合对于成员关系测试很有用。
>>> tech_stocks set(['AAPL', 'IBM', 'MSFT']) >>> 'IBM' in tech_stocks True >>> 'FB' in tech_stocks False >>>集合对于消除重复也很有用。
names = ['IBM', 'AAPL', 'GOOG', 'IBM', 'GOOG', 'YHOO'] unique = set(names) # unique = set(['IBM', 'AAPL','GOOG','YHOO'])其它集合操作:
names.add('CAT') # Add an item names.remove('YHOO') # Remove an item s1 | s2 # Set union s1 & s2 # Set intersection s1 - s2 # Set difference 练习在这些练习中,你开始构建的程序是本课程剩余部分使用的主要程序之一。请在 Work/report.py 文件中工作。
练习 2.4:包含元组的列表Data/portfolio.csv 文件包含投资组合中的股票列表。在 练习 1.30 中,你编写了一个读取该文件并执行简单计算的 portfolio_cost(filename) 函数。
代码看起来应该像下面这样:
# pcost.py import csv def portfolio_cost(filename): '''Computes the total cost (shares*price) of a portfolio file''' total_cost = 0.0 with open(filename, 'rt') as f: rows = csv.reader(f) headers = next(rows) for row in rows: nshares = int(row[1]) price = float(row[2]) total_cost += nshares * price return total_cost请使用这些代码作为指导,创建一个新文件 report.py 。在 report.py 文件中,定义 read_portfolio(filename) 函数,该函数打开 Data/portfolio.csv 文件并将其读入到包含元组的列表中。为此,你需要对上面的代码做一些小修改。
首先,创建一个最初设为空列表的变量,而不是定义 total_cost = 0。例如:
portfolio = []接着,把每一行准确地存储到元组中(就像在上次的练习中做的那样),然后把元组追加到列表中,而不是合计总的费用。
for row in rows: holding = (row[0], int(row[1]), float(row[2])) portfolio.append(holding)最后,返回得到的portfolio 列表。
请交互式地试验函数(提醒,要执行此操作,首先需要在解释器运行 report.py 程序)。
提示:当在终端执行文件的时候,请使用 -i 参数。
>>> portfolio = read_portfolio('Data/portfolio.csv') >>> portfolio [('AA', 100, 32.2), ('IBM', 50, 91.1), ('CAT', 150, 83.44), ('MSFT', 200, 51.23), ('GE', 95, 40.37), ('MSFT', 50, 65.1), ('IBM', 100, 70.44)] >>> >>> portfolio[0] ('AA', 100, 32.2) >>> portfolio[1] ('IBM', 50, 91.1) >>> portfolio[1][1] 50 >>> total = 0.0 >>> for s in portfolio: total += s[1] * s[2] >>> print(total) 44671.15 >>>创建的包含元组的列表非常类似于二维(2-D)数组。例如,使用诸如 portfolio[row][column] ( row 和column 是整数)的查找来访问特定的列和行。