目录 | 上一节 (1.7 函数) | 下一节 (2.2 容器)python
本节以元组和字典为表明介绍数据结构。git
Python 有一些原始数据类型:github
email_address = None
None
经常使用做可选值或缺失值的占位符。它在条件语句中计算为 False
。数据库
if email_address: send_email(email_address, msg)
实际的程序具备更复杂的数据。例如,关于股票的持有信息:编程
100 shares of GOOG at $490.10
这是一个包含三个部分的“对象”:segmentfault
元组是分组在一块儿的值的集合。数组
示例:数据结构
s = ('GOOG', 100, 490.1)
有时候会在语法上省略 ()
。编程语言
s = 'GOOG', 100, 490.1
特殊状况(0 元组,1 元组)。函数
t = () # An empty tuple w = ('GOOG', ) # A 1-item tuple
元组通常用来表示简单的记录或结构。
一般,它是由多个部分组成的单个对象。这有一个很好的类比:元组就像数据库表中的一行。
元组的内容是有序的(相似于数组)。
s = ('GOOG', 100, 490.1) name = s[0] # 'GOOG' shares = s[1] # 100 price = s[2] # 490.1
可是,元组的内容没法修改。
>>> s[1] = 75 TypeError: object does not support item assignment
你能够基于当前元组建立一个新元组。
s = (s[0], 75, s[2])
元组更多的是把相关的项打包到一个实体(entity)中。
s = ('GOOG', 100, 490.1)
而后,该元组很容易做为单个对象传递给程序的其它部分。
要在其它地方使用元组,能够把元组的各部分拆包为变量。
name, shares, price = s print('Cost', shares * price)
左侧变量的数目必须与元组的结构匹配。
name, shares = s # ERROR Traceback (most recent call last): ... ValueError: too many values to unpack
元组看起来像只读列表。可是,元组最经常使用于由多个部分组成的单项。列表一般是类型相同的项的集合,
record = ('GOOG', 100, 490.1) # A tuple representing a record in a portfolio symbols = [ 'GOOG', 'AAPL', 'IBM' ] # A List representing three stock symbols
字典是键到值的映射。有时,字典也称为哈希表(hash table)或关联数组(associative array)。键用做访问值的索引。
s = { 'name': 'GOOG', 'shares': 100, 'price': 490.1 }
要从字典中获取值,请使用键名。
>>> print(s['name'], s['shares']) GOOG 100 >>> s['price'] 490.10 >>>
要添加或修改值,请使用键名进行分配。
>>> s['shares'] = 75 >>> s['date'] = '6/6/2007' >>>
要删除值,请使用 del
语句。
>>> del s['date'] >>>
当存在不少不一样的值而且可能会修改或操做这些值时,字典颇有用。字典使代码更具可读性。
s['price'] # vs s[2]
在上次的几个练习中,编写了一个取数据文件 Data/portfolio.csv
的程序 。使用 csv
模块,能够轻松地逐行读取文件。
>>> import csv >>> f = open('Data/portfolio.csv') >>> rows = csv.reader(f) >>> next(rows) ['name', 'shares', 'price'] >>> row = next(rows) >>> row ['AA', '100', '32.20'] >>>
尽管读取文件很容易,可是与读取数据相比,一般使用数据作更多的事情。例如,也许想存储它并对其执行一些计算。不幸的是,原始的数据“行”并不能这样作。例如,即便是简单的数学计算也不行。
>>> row = ['AA', '100', '32.20'] >>> cost = row[1] * row[2] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: can't multiply sequence by non-int of type 'str' >>>
要执行更多的操做,一般须要以某种方式解释原始数据,并将其转换为更有用的对象类型,以便之后处理。有两种简单的方式能够选择:元组或者字典。
在交互式提示符下,建立如下表明上一行的元组,但数字列要转换为恰当的数字。
>>> t = (row[0], int(row[1]), float(row[2])) >>> t ('AA', 100, 32.2) >>>
使用这种方式,如今可使用股份数目乘以价格来计算总价,
>>> cost = t[1] * t[2] >>> cost 3220.0000000000005 >>>
在 Python 中,数学没用了吗?结果为何是 3220.0000000000005?
这是计算机上浮点硬件的产物,只能在二进制(而不是十进制)中准确表示小数。即便是涉及十进制小数的简单计算,也会引入小的偏差。这很正常,若是你以前没有见过,可能会有点惊讶。
虽然在全部使用浮点小数的编程语言中都会发生这种状况,可是打印的时候能够把它隐藏,例如:
>>> print(f'{cost:0.2f}') 3220.00 >>>
元组是只读的。能够经过尝试把股份数目改成 75 来验证这点。
>>> t[1] = 75 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment >>>
尽管没法更改元组的内容,可是始终能够建立一个全新的元组来替换旧的元组。
>>> t = (t[0], 75, t[2]) >>> t ('AA', 75, 32.2) >>>
每当像这样从新分配现有变量名时,旧值就会被丢弃。虽然上面的赋值可能看起来像在修改元组,但其实是在建立一个新的元组,而且将旧的元组丢弃。
元组一般用于将值打包或拆包到变量中。请尝试如下操做:
>>> name, shares, price = t >>> name 'AA' >>> shares 75 >>> price 32.2 >>>
取上面的变量并将其打包回元组中:
>>> t = (name, 2*shares, price) >>> t ('AA', 150, 32.2) >>>
能够建立字典来替代元组。
>>> d = { 'name' : row[0], 'shares' : int(row[1]), 'price' : float(row[2]) } >>> d {'name': 'AA', 'shares': 100, 'price': 32.2 } >>>
计算持有的总价:
>>> cost = d['shares'] * d['price'] >>> cost 3220.0000000000005 >>>
将此示例与上面涉及元组的相同的计算进行比较,将股份数目修改成 75。
>>> d['shares'] = 75 >>> d {'name': 'AA', 'shares': 75, 'price': 32.2 } >>>
与元组不一样,字典能够自由修改。添加一些属性:
>>> d['date'] = (6, 11, 2007) >>> d['account'] = 12345 >>> d {'name': 'AA', 'shares': 75, 'price':32.2, 'date': (6, 11, 2007), 'account': 12345} >>>
若是将一个字典转换为列表,则将得到其全部的键:
>>> list(d) ['name', 'shares', 'price', 'date', 'account'] >>>
相似地,若是使用 for
语句对字典进行迭代,则将得到其全部的键。
>>> for k in d: print('k =', k) k = name k = shares k = price k = date k = account >>>
尝试使用这个同时执行查找的变体:
>>> for k in d: print(k, '=', d[k]) name = AA shares = 75 price = 32.2 date = (6, 11, 2007) account = 12345 >>>
也可使用 keys()
方法得到全部的键:
>>> keys = d.keys() >>> keys dict_keys(['name', 'shares', 'price', 'date', 'account']) >>>
在这里,keys()
稍微有点不一样,它返回的是一个 dict_keys
对象。
这是对原始字典的覆盖,它始终提供当前字典的键——即便字典改变了。例如,试试一下操做:
>>> del d['account'] >>> keys dict_keys(['name', 'shares', 'price', 'date']) >>>
请注意,尽管没有再次调用 d.keys()
,但键'account'
消失了。
一个更优雅地一块儿使用键和值的方式是使用 items()
方法。这能够得到键值组成的元组 (key, value)
。
>>> items = d.items() >>> items dict_items([('name', 'AA'), ('shares', 75), ('price', 32.2), ('date', (6, 11, 2007))]) >>> for k, v in d.items(): print(k, '=', v) name = AA shares = 75 price = 32.2 date = (6, 11, 2007) >>>
若是有相似于 items
的元组,那么可使用 dict()
函数建立一个字典。请尝试如下操做:
>>> items dict_items([('name', 'AA'), ('shares', 75), ('price', 32.2), ('date', (6, 11, 2007))]) >>> d = dict(items) >>> d {'name': 'AA', 'shares': 75, 'price':32.2, 'date': (6, 11, 2007)} >>>