Python内置数据结构之字典dict
1. 字典
字典是Python中唯一的内置映射类型,其中的值不按顺序排列,而是存储在键下。键可能是数(整数索引)、字符串或元组。字典(日常生活中的字典和Python字典)旨在让你能够轻松地找到特定的单词(键),以获悉其定义(值)。
字典用{}括起开。
在很多情况下,使用字典都比使用列表更合适。下面是Python字典的一些用途:
表示棋盘的状态,其中每个键都是由坐标组成的元组;
存储文件修改时间,其中的键为文件名;
数字电话/地址簿。
1.1 函数 dict
可使用函数dict从其他映射(如其他字典)或键-值对序列创建字典。函数dict实际上是一个类,也是一个工厂函数,目前,这种差别不重要。
这可能是函数dict最常见的用法,但也可使用一个映射实参来调用它,这将创建一个字典,其中包含指定映射中的所有项。像函数list、 tuple和str一样,如果调用这个函数时没有提供任何实参,将返回一个空字典。从映射创建字典时,如果该映射也是字典(毕竟字典是Python中唯一的内置映射类型),可不使用函数dict,而是使用字典方法copy。
>>> items = [('name', 'Alex'), ('age', 22)]
>>> d = dict(items)
>>> d
{'name': 'Alex', 'age': 22}
>>> d['name']
'Alex'
>>>
还可使用关键字实参来调用这个函数,如下所示:
>>> d = dict(name='alex', age=22)
>>> d
{'name': 'alex', 'age': 22}
>>>
1.2 创建和使用字典
字典以类似于下面的方式表示:
phonebook = {'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'}
字典由键及其相应的值组成,这种键-值对称为项(item)。在前面的示例中,键为名字,而值为电话号码。每个键与其值之间都用冒号(:)分隔,项之间用逗号分隔,而整个字典放在花括号内。空字典(没有任何项)用两个花括号表示,类似于下面这样: {}。
注意:在字典(以及其他映射类型)中,键必须是独一无二的,而字典中的值无需如此。
基本的字典操作
a. 字典的基本行为在很多方面都类似于序列。
i. len(d)返回字典d包含的项(键-值对)数。
ii. d[k]返回与键k相关联的值。
iii. d[k] = v将值v关联到键k。
iv. del d[k]删除键为k的项。
v. k in d检查字典d是否包含键为k的项。
b. 字典和列表一些重要的不同之处
i. 键的类型:字典中的键可以是整数,但并非必须是整数。字典中的键可以是任何不可变的类型,如浮点数(实数)、字符串或元组。
ii. 自动添加:即便是字典中原本没有的键,也可以给它赋值,这将在字典中创建一个新项。然而,如果不使用append或其他类似的方法,就不能给列表中没有的元素赋值。
iii. 成员资格:表达式k in d(其中d是一个字典)查找的是键而不是值,而表达式v in l(其中l是一个列表)查找的是值而不是索引。这看似不太一致,但你习惯后就会觉得相当自然。毕竟如果字典包含指定的键,检查相应的值就很容易。
提示:相比于检查列表是否包含指定的值,检查字典是否包含指定的键的效率更高。数据结构越大,效率差距就越大。
1.3 字典的常用操作
info = { 'stu101': "TengLan Wu", 'stu102': "longZe Luola", 'stu103': "XiaoZe Maliya" } # print(info["stu101"]) # add print(info) info["stu101"] = "武藤兰" # 修改 info["stu104"] = "Cangjingkong" # 不存在,创建 print(info) ——> {'stu101': 'TengLan Wu', 'stu102': 'longZe Luola', 'stu103': 'XiaoZe Maliya'} {'stu101': '武藤兰', 'stu102': 'longZe Luola', 'stu103': 'XiaoZe Maliya', 'stu104': 'Cangjingkong'} # del print(info) info.pop("stu101") # 如果不指定,随机删 # del info["stu101"] # info.popitem() # 随机删 print(info) ——> {'stu101': 'TengLan Wu', 'stu102': 'longZe Luola', 'stu103': 'XiaoZe Maliya'} {'stu102': 'longZe Luola', 'stu103': 'XiaoZe Maliya'} # find print(info) print(info.get("stu104")) # Determine whether the dictionary has data print('stu104' in info) # info.has_key("103") in py2.x ——> {'stu101': 'TengLan Wu', 'stu102': 'longZe Luola', 'stu103': 'XiaoZe Maliya'} None False # 分别打印values keys print(info) print(info.values()) print(info.keys()) ——> {'stu101': 'TengLan Wu', 'stu102': 'longZe Luola', 'stu103': 'XiaoZe Maliya'} dict_values(['TengLan Wu', 'longZe Luola', 'XiaoZe Maliya']) dict_keys(['stu101', 'stu102', 'stu103']) # setdefault 在字典中取值,取到,将stu103返回,取不到stu106,创建 print(info) print(info.setdefault("stu103", "Alex")) print(info) print(info.setdefault("stu106", "Alex")) print(info) ——> {'stu101': 'TengLan Wu', 'stu102': 'longZe Luola', 'stu103': 'XiaoZe Maliya'} XiaoZe Maliya {'stu101': 'TengLan Wu', 'stu102': 'longZe Luola', 'stu103': 'XiaoZe Maliya'} Alex {'stu101': 'TengLan Wu', 'stu102': 'longZe Luola', 'stu103': 'XiaoZe Maliya', 'stu106': 'Alex'} # update 字典合并,原有且更改的,更新;原没有的,增加 print(info) print(info) b = { "stu101": "Daqiao", 1: 3, 2: 4 } info.update(b) print(info) ——> {'stu101': 'TengLan Wu', 'stu102': 'longZe Luola', 'stu103': 'XiaoZe Maliya'} {'stu101': 'Daqiao', 'stu102': 'longZe Luola', 'stu103': 'XiaoZe Maliya', 1: 3, 2: 4} # items 将字典转化成列表 print(info) print(info.items()) ——> {'stu101': 'TengLan Wu', 'stu102': 'longZe Luola', 'stu103': 'XiaoZe Maliya'} dict_items([('stu101', 'TengLan Wu'), ('stu102', 'longZe Luola'), ('stu103', 'XiaoZe Maliya')]) # 高效 通过索引,直接取出info print(info) for i in info: print(i, info[i]) print("----------") # 低效 将字典转成列表(数据量很大时,转很长时间,机器奔溃) 列表中每一个元素都是一个小元组 for k, v in info.items(): print(k, v) # fromkeys [1, {"name": "alex"}, 444] 共用一个地址空间,类似浅copy c = dict.fromkeys([6, 7, 8], "test") c2 = dict.fromkeys([6, 7, 8], [1, {"name": "alex"}, 444]) print(c) print(c2) c2[7][1]['name'] = "jack" print(c2) ——> {6: 'test', 7: 'test', 8: 'test'} {6: [1, {'name': 'alex'}, 444], 7: [1, {'name': 'alex'}, 444], 8: [1, {'name': 'alex'}, 444]} {6: [1, {'name': 'jack'}, 444], 7: [1, {'name': 'jack'}, 444], 8: [1, {'name': 'jack'}, 444]} # copy 返回一个新字典,其包含的键值对与原来的字典相同(这个方法执行的是浅复制,因为值本身是原件,而非副本)。 >>> x = {'username': 'admin', 'machines': ['foo', 'bar', 'baz']} >>> y = x.copy() >>> y['username'] = 'mlh' >>> y['machines'].remove('bar') >>> y {'username': 'mlh', 'machines': ['foo', 'baz']} >>> x {'username': 'admin', 'machines': ['foo', 'baz']} 当替换副本中的值时,原件不受影响。然而,如果修改副本中的值(就地修改而不是替换) ,原件也将发生变化,因为原件指向的也是被修改的值(如这个示例中的'machines'列表所示)。 # deepcopy 为避免这种问题,一种办法是执行深复制,即同时复制值及其包含的所有值,等等。为此,可使用模块copy中的函数deepcopy。 >>> from copy import deepcopy >>> d = {} >>> d['names'] = ['Alfred', 'Bertrand'] >>> c = d.copy() >>> dc = deepcopy(d) >>> d['names'].append('Clive') >>> c {'names': ['Alfred', 'Bertrand', 'Clive']} >>> dc {'names': ['Alfred', 'Bertrand']}
字典方法示例
# 一个使用get()的简单数据库 # 一个将人名用作键的字典。每个人都用一个字典表示, # 字典包含键'phone'和'addr',它们分别与电话号码和地址相关联 people = { 'Alice': { 'phone': '2341', 'addr': 'Foo drive 23' }, 'Beth': { 'phone': '9102', 'addr': 'Bar street 42' }, 'Cecil': { 'phone': '3158', 'addr': 'Baz avenue 90' } } # 电话号码和地址的描述性标签,供打印输出时使用 labels = { 'phone': 'phone number', 'addr': 'address' } name = input('Name: ') # 要查找电话号码还是地址? request = input('Phone number (p) or address (a)? ') # 使用正确的键: key = request # 如果request既不是'p'也不是'a' if request == 'p': key = 'phone' if request == 'a': key = 'addr' # 使用get提供默认值 person = people.get(name, {}) label = labels.get(key, key) result = person.get(key, 'not available') print("{}'s {} is {}.".format(name, label, result)) 执行结果: Name: jj Phone number (p) or address (a)? a jj's address is not available.

浙公网安备 33010602011771号