2.3 通过字典存放“键-值对”类型的数据
Python中的字典(Dict)也是数组的一种,在其中能以“键-值对”(Key-Value Pair)的方式存放多个数据。在字典中,是用基于哈希表的方式来保存数据,所以数据查找的速度非常快,哪怕其中存储的数据再多,也能以O(1)的计算复杂度找到数据,即基本是一次查找就命中。
和其他程序设计语言一样,Python中的字典一般是用来存储多个数据,而不是一个。
2.3.1 针对字典的常见操作
字典主要用来存储“键-值对”的数据,在DictDemo.py范例程序中,展示了在项目中的常见操作字典的用法。
1 # !/usr/bin/env python 2 # coding=utf-8 3 # 定义并打印字典 4 onePersonInfo={'name': 'Mike', 'age': 7} 5 print(onePersonInfo) # {'age': 7, 'name': 'Mike'} 6 onePersonInfo['age']=8 # 修改其中的元素 7 print(onePersonInfo) # age会变成8 8 print(onePersonInfo['name'] ) # Mike 9 del onePersonInfo['name'] 10 print(onePersonInfo) # age会变成8 #{'age': 8} 11 print(onePersonInfo.get('name')) # None 12 print(onePersonInfo.get('age')) # 8 13 if 'name' not in onePersonInfo: 14 onePersonInfo['name']="Mike" # 增加新元素 15 print(onePersonInfo.get('name')) # Mike 16 # 通过for循环遍历字典 17 for i,v in onePersonInfo.items(): 18 print(i,v) # 得到键和值
在上述范例程序中的第4行是通过大括号(即{})来定义字典,而且是通过冒号的方式来定义“键-值对”,比如用'name': 'Mike'的形式,即表示name这个键的值是Mike。请注意,多个“键-值对”之间是用逗号分隔。
在第6行中,演示了可以通过方括号的方式来访问onePersonInfo这个字典类型中的'age'键,并把它的值改成8,通过第7行的打印语句就能看到这一修改后的结果。
可以像第9行那样用del语句,还是通过方括号的形式,删除字典中指定的“键-值对”,完成删除后,如果通过第11行的get语句来获取'name',则会返回None,即表示没找到对应的值。这里get的作用是获取字典中指定键对应的值,比如在第12行中,可以通过get,输出'age'这个键对应的值。
还可以通过in和not in来判断在字典里有没有指定的键,比如在第13行中,在if语句中用not in来判断onePersonInfo这个字典里是否有'name',由于之前在第9行中已经删除了这个键,因此这里执行第14行的代码,在字典里增加'name'等于"Mike"这个“键-值对”。
在第17行和18行中,通过for循环遍历了onePersonInfo字典,其中值得关注的是,首先是通过items方法获取字典中所有的“键-值对”,其次是在for循环中通过i和v来映射字典中的“键-值对”。第17行程序语句中的i和v的变量名可以随便起,和第18行print语句中保持一致即可。
2.3.2 在字典中以复杂的格式存储多个数据
在2.3.1小节中,我们在字典中存放了一条关于人的信息,比如名字叫Mike,年龄是7岁。而在实际项目中,往往会在字典中存储相同数据类型格式的多个数据,而且还会出现在字典中嵌套了列表等的复杂用法。在下面的DictMoreData.py范例程序中将演示这些用法。
1 # !/usr/bin/env python 2 # coding=utf-8 3 # 以列表方式定义Mike和Tom两个人的账户 4 accountsInfoList=[{'name': 'Mike', 'balance': 100,'stockList':['600123','600158']},{'name': 'Tom', 'balance': 200,'stockList':['600243','600558']} ] 5 # 通过for循环,依次输出列表中的元素 6 for item in accountsInfoList: 7 print(item['name'],) # print后带逗号表示不换行 8 print(item['balance'],) 9 print(item['stockList']) 10 # 以字典的方式定义 11 accountInfoDict={ 'Peter':{'balance': 100,'stockList':['600123', '600158'] },'Tom': { 'balance': 200,'stockList':['600243','600558']} } 12 # 输出{'balance': 100, 'stockList': ['600123', '600158']} 13 print(accountInfoDict.get('Peter')) 14 PeterAccount={ 'Peter':{'balance': 200,'stockList':['600223','600158',600458] }} 15 accountInfoDict.update(PeterAccount) 16 print(accountInfoDict.get('Peter')) # 能看到更新后的内容 17 JohnAccount={ 'John':{'balance': 200,'stockList':[] }} 18 accountInfoDict.update(JohnAccount) 19 # 利用双层循环打印 20 for name,account in accountInfoDict.items(): 21 print ("name is %s:"%(name)), # 输出name后不换行 22 for key,value in account.items(): 23 print(value,) 24 Print() # 输完一个人的信息后换行
在第4行中用方括号的方式定义了accountsInfoList列表对象,在其中用大括号的方式定义了两个“键-值对”类型的账户信息,在第6行到第9行的for循环里,依次输出了这两个账户信息里的三个“键-值对”,输出的结果如下所示:
Mike 100 ['600123', '600158'] Tom 200 ['600243', '600558']
在第11行中用大括号的方式定义了accountInfoDict这个字典类型的数据,其中同样存放了两个人的账户信息。在实际项目的集合对象中,不可能只存储一个数据,大家要掌握这种用列表或字典保存多个数据的方式。
字典对象中的另一个比较实用的方法是update,它有两层含义,如果字典对象中已经有相同的键,那么就用对应的值更新原来的值。比如在第14行中,更新了Peter的balance和stockList信息,在第15行的update语句中,就会用第14行中定义的对应值(即balance和stockList)更新掉原来的值,通过第16行的print语句就能看到这一更新后的结果。
update语句另外的一层含义是,如果在字典中没有待更新的“键”,那么就会插入对应的“键-值对”。比如在第17行中,定义原本不存在于accountInfoDict字典对象的JohnAccount,一旦执行了第18行的update语句就会完成更新,后面的打印语句即可看到插入更新后的结果。
由于在accountInfoDict这个字典类对象中存储了结构比较复杂的对象,比如值也是字典类型,而stockList是列表类型,因此在20行到第24行中用双层for循环来遍历这个字典对象。
其中,在第21行中输出了每个字典中的“键”,即姓名信息,输完后不换行。在第22行的内层for循环里调用了item方法,依次遍历了accountInfoDict对象中的“值”信息(也是字典类型的对象),遍历完一个人的账户信息后,会在第24行中通过print语句进行换行,这段语句的输出结果如下,其中包含新增的John的账户信息。
name is Peter: 200 ['600223', '600158', 600458] name is John: 200 [] name is Tom: 200 ['600243', '600558']
虽然可以在字典中存放各种类型的数据,但应当用同一种格式存储多个数据,比如在第11行中用'name':{'balance': xx, 'stockList':[xx]}的格式输入并存储多个人的账户信息。
这样做的好处是,由于事先约定好能用同一种方式来解析字典中的数据,因此解析数据的规则是统一的。这点在Java等语言中能用泛型来保证,但在Python语言中,如果两个数据的格式不一致,也不会出现语法错误,但这样的做法就会造成处理方式的不统一。所以在使用Python字典类对象时,程序员应当时刻注意这点。