本文介绍本系列教程最后一个数据结构——字典


在现实生活中,查英语字典的时候,我们通常根据单词来查找意思。而python中的字典也是类似的,根据特定的 “键”(单词)来查找 “值”(意思)。

字典的基本使用

下面以电话簿为例,我们的电话簿记录的是电话号码。当要查找电话号码时,我们根据人名来查找其电话号码,所以人名就是字典的键,电话号码就是字典的值。假设有下面这样的人名和电话号码的电话簿:

  1. 人名=>电话
  2. Aganzo=>1230
  3. Jack=>0221
  4. Lee=>1354
  5. Emilie=>2479

创建字典

现在我们来创建一个字典来表示这个电话簿:

  1. >>> phonebook={'Aganzo':'1230', 'Jack':'0221', 'Lee':'1354', 'Emilie':'2479'}
  2. >>> phonebook
  3. {'Aganzo': '1230', 'Jack': '0221', 'Lee': '1354', 'Emilie': '2479'}
  4. >>>

从上面可以看出,创建字典的基本格式为{ 键1:值1, 键2:值2, 键3:值3 ...}。除了这种方法,我们还可以通过dict函数传递关键字参数来创建字典,像下面这样:

  1. >>> phonebook = dict(Aganzo='1230', Jack='0221', Lee='1354', Emilie='2479') # 关键字参数就是字典的键,参数值就是字典的值
  2. >>> phonebook
  3. {'Aganzo': '1230', 'Jack': '0221', 'Lee': '1354', 'Emilie': '2479'}
  4. >>>

我们常用第一种方式创建字典,第二种方式比较少用,而且第二种方式有一个缺点:因为关键字参数会变为字典的键,所以键必须符合参数的命名规则(字母或下划线_开头,其后是数字、字母或下划线)。

补充:创建空字典有两种方法,一种是直接使用{};另一种是调用dict函数时,参数留空,即dict();像键:值这样的东西叫做字典的 “项”

字典基本操作

字典的基本操作有:

先来说“查”:我们可以通过名字来查找电话簿中的电话号码,在字典中类似这样,通过“键”来查“值”,基本格式为字典[键]

  1. >>> phonebook['Aganzo']
  2. '1230'
  3. >>> phonebook['Jack']
  4. '0221'
  5. >>> phonebook['Lily']
  6. Traceback (most recent call last):
  7. File "<stdin>", line 1, in <module>
  8. KeyError: 'Lily'
  9. >>>

从上面的代码可以看出,我们的“电话簿”中不存在Lily的电话号码,可知,当字典中不存在要查的元素时,python会提示报错。我们可以在查之前确认字典中是否有对应的项,使用成员运算符in

  1. >>> 'Lily' in phonebook # 不存在
  2. False
  3. >>> 'Jack' in phonebook # 存在
  4. True
  5. >>>

或者查看“电话簿”中所有人的电话号码:

  1. >>> for key in phonebook:
  2. ... print('%s=>%s' % (key, phonebook[key]))
  3. ...
  4. Aganzo=>1230
  5. Jack=>0221
  6. Lee=>1354
  7. Emilie=>2479
  8. >>>

再来说“改”:此时得知Lee更换了电话号码为112233,需要对电话簿进行更改,使用如下代码:

  1. >>> phonebook['Lee'] = '112233'
  2. >>> phonebook
  3. {'Aganzo': '1230', 'Jack': '0221', 'Lee': '112233', 'Emilie': '2479'}
  4. >>>

再到“增”:假设新认识了一位朋友Zieg,得到了朋友的电话号码为123456,需要在“电话簿”中新增一项,和“改”操作一样,使用赋值运算符=

  1. >>> phonebook['Zieg'] = '123456'
  2. >>> phonebook
  3. {'Aganzo': '1230', 'Jack': '0221', 'Lee': '112233', 'Emilie': '2479', 'Zieg': '123456'}
  4. >>>

最后说“删”:朋友Jack与你绝交了(世事无常╮(╯▽╰)╭),你决定删除他的联系方式,此时你狠心地运行了下面的代码:

  1. >>> del phonebook['Jack']
  2. >>> phonebook
  3. {'Aganzo': '1230', 'Lee': '112233', 'Emilie': '2479', 'Zieg': '123456'}
  4. >>>

“电话簿”中再也没有了Jack的电话号码……

小结

好了,一个简单的示例过后,相信大家能理解字典的使用方法了,让我们来一个小小的总结:

创建字典的方法:

  • 通过花括号创建 x = {键1:值1, 键2:值2, 键3:值3 ...}
  • 通过dict函数创建 x = dict(key1=value1, key2=value2, key3=value3 ...)
  • 创建空字典可以使用 x = {}x = dict()

字典的基本操作:

  • 增:x['abc'] = 123 (键'abc'不存在)
  • 删:del x['abc']
  • 改:x['abc] += 1x['abc'] = 2x['abc'] *= 10……(键'abc'存在)
  • 查:result = x['abc']print(x['abc'])……(键'abc'存在)

补充:字典的用法和列表类似,只不过列表索引元素的时候使用的是数字作键,而字典大多数时候使用字符串索引元素。


关于字典的键,还有一点是要说清楚的:前面我们使用字典的时候都是使用了字符串类型的键,可我没有说字典的键只能是字符串!

实际上,字典的键可以是任意的不可变类型,如:字符串(最常用)、元组、浮点数、整数。


字典方法

字典也是对象,和列表一样,字典也提供了一些实用的方法,下面是介绍

clear

clear方法用于清空字典中的所有项:

  1. >>> d = {'name':'feather', 'age':18}
  2. >>> d
  3. {'name': 'feather', 'age': 18}
  4. >>> d.clear()
  5. >>> d
  6. {}
  7. >>>

这个方法是原地的操作,意思就是操作对象是在字典本身,这和直接将变量赋值为空字典是不一样的,从下面的例子可以看出:

  1. >>> x = {'a':1}
  2. >>> y = x # y变量引用的字典和x变量引用的是同一个字典
  3. >>> x = {} # 将x变量引用改为另一个字典,这个字典是空字典
  4. >>> x
  5. {}
  6. >>> y # y变量引用的字典没有被改变
  7. {'a': 1}
  8. >>>

copy

copy方法用于返回一个新字典,这个新字典和原来的字典拥有相同的项:

  1. >>> x = {'name':'feather', 'blog':['https://blog.csdn.net/lonely_feather', 'https://featherl.gitee.io/']}
  2. >>> y = x.copy()
  3. >>> y['name'] = 'Lee'
  4. >>> y['blog'].append('https://www.cnblogs.com/featherl/')
  5. >>> x
  6. {'name': 'feather', 'blog': ['https://blog.csdn.net/lonely_feather', 'https://featherl.gitee.io/', 'https://www.cnblogs.com/featherl/']}
  7. >>> y
  8. {'name': 'Lee', 'blog': ['https://blog.csdn.net/lonely_feather', 'https://featherl.gitee.io/', 'https://www.cnblogs.com/featherl/']}
  9. >>>

可以看到,y字典是从x复制而来的,所以改变y字典的键为'name'的项的时候并不影响x字典,要注意的是,y['blog'].append('https://www.cnblogs.com/featherl/') 这句代码不属于修改y字典,这是修改y字典的键为'blog'的项引用的列表,而y字典和x字典的'blog'项引用的是同一个列表(因为y字典的项是从x字典中复制而来的),所以修改这个列表的时候,在x和y两个字典上都可以看到效果。

这种问题是因为copy方法是“浅复制”,copy方法仅仅把相同的值存储到了一个新的字典里,要想避免这种问题,需要使用“深复制”,可以使用copy模块的deepcopy函数来实现:

  1. >>> from copy import deepcopy
  2. >>> x = {'list':[1,2,3]}
  3. >>> y = deepcopy(x)
  4. >>> y['list'].append(4)
  5. >>> x
  6. {'list': [1, 2, 3]}
  7. >>> y
  8. {'list': [1, 2, 3, 4]}
  9. >>>

fromkeys

fromkeys方法用给定的键创建新字典,每个键对应的默认值都为None:

  1. >>> {}.fromkeys(['name'])
  2. {'name': None}
  3. >>> dict.fromkeys(['name', 'age'])
  4. {'name': None, 'age': None}

上面代码的第一个例子中,我们创建了一个空字典,然后使用这个空字典的fromkeys方法创建了一个新字典,第二个例子中,我们直接使用dict这个类(实际上dict不是函数,是一个“类”)的fromkeys方法创建新字典。

我们还可以自己设置默认值:

  1. >>> dict.fromkeys(['name', 'age'], '???')
  2. {'name': '???', 'age': '???'}

get

get方法使用给定的键访问字典中的项,不过,如果字典中不存在该项时,get方法返回默认值None,而不是报错:

  1. >>> x = {'name':'Lee'}
  2. >>> x.get('age')
  3. >>> print(x.get('name'))
  4. Lee
  5. >>> print(x.get('age'))
  6. None

同样的,这个默认值也是可以自己设定的:

  1. >>> x = {'name':'Lee'}
  2. >>> x.get('age', '???')
  3. '???'

update

update方法将一个新字典合并到当前字典,当存在相同的键,用新字典的值进行覆盖:

  1. >>> x = {'name':'Lee'}
  2. >>> x = {'name':'Lee', 'blog':'https://featherl.gitee.io'}
  3. >>> y = {'name':'feather', 'age':18}
  4. >>> x.update(y)
  5. >>> x
  6. {'name': 'feather', 'blog': 'https://featherl.gitee.io', 'age': 18}

pop

pop方法用来返回指定键的项,并将该项从字典中移除:

  1. >>> x = {1:1, 2:2, 3:3}
  2. >>> x.pop(1)
  3. 1
  4. >>> x
  5. {2: 2, 3: 3}

上面的例子同时也证明了字典的键不一定是字符串。

popitem

popitem方法随机挑选一个项返回,并删除这个项。字典不同于列表,字典的项是没有顺序,不同的机器或者不同版本的python,其字典存储项的顺序可能是不一样的,故popitem方法具体处理哪一项是没法预测的。

使用举例如下:

  1. >>> x = {1:1, 2:2, 3:3}
  2. >>> x.pop
  3. x.pop( x.popitem(
  4. >>> help(x.popitem)
  5. >>> x.popitem()
  6. (3, 3)
  7. >>> x.popitem()
  8. (2, 2)
  9. >>> x.popitem()
  10. (1, 1)
  11. >>> x.popitem()
  12. Traceback (most recent call last):
  13. File "<stdin>", line 1, in <module>
  14. KeyError: 'popitem(): dictionary is empty'

当字典为空的时候,该方法抛出错误。

items

items方法返回字典的所有的项,每个项为一个形式为(key, value)的元组,返回的类型是一种类似列表的类型,可以使用for循环迭代,但是没有列表的方法,最好先使用list转换成列表:

  1. >>> x = {'name':'Lee', 'age':18}
  2. >>> x.items()
  3. dict_items([('name', 'Lee'), ('age', 18)])
  4. >>> list(x.items()) # 转换成列表
  5. [('name', 'Lee'), ('age', 18)]

注意:在python2中此方法还有后面的keys、values方法返回的就是列表类型,不过我们学的是python3,要注意区分。

类似items的方法还有:

  • keys方法返回字典的所有的键(类似列表的类型)
  • values方法返回字典的所有的值(类似列表的类型)

到此为止,本系列教程的python数据结构已经介绍完了,在本系列教程只是介绍了python中如何使用常用数据结构,并没有讲实现原理。而数据结构在计算机领域是不可或缺的,希望对数据结构了解甚少的读者可以认真学习一下数据结构的相关知识。

等学习完文件操作后,我们将用一个小项目实践一下(其实忽略文件操作,目前学到的知识还是可以做很多东西的),敬请期待! ( ̄︶ ̄)↗

python教程(七)·字典的更多相关文章

  1. 简明python教程七----面向对象的编程(下)

    继承:类之间的类型和子类型关系 代码重用:SchoolMember类被称为 基本类或超类,而Teacher和Student类被称为导出类或者子类 #!/usr/bin/python #Filename ...

  2. 简明python教程七----面向对象的编程

    根据操作数据的函数或语句块来设计程序的,被称为面向过程的编程. 把数据和功能结合起来,用称为对象的东西包裹起来的组织程序的方法,称为面向对象的编程理念. 类和对象是面向对象编程的两个主要方面.类创建一 ...

  3. 《简明python教程》笔记一

    读<简明Python教程>笔记: 本书的官方网站是www.byteofpython.info  安装就不说了,网上很多,这里就记录下我在安装时的问题,首先到python官网下载,选好安装路 ...

  4. python教程(零)·前言

    本教程是作者根据自己学习python的经验写下的,一来是想将经验分享给对python同样感兴趣的小白(大神请忽略),二来是想借此加深本人对python的理解,温故而知新. 学习基础 本教程面向的读者, ...

  5. (原+转)简明 Python 教程:总结

     简明 Python 教程 说明:本文只是对<简明Python教程>的一个总结.请搜索该书查看真正的教程. 第3章 最初的步骤 1. Python是大小写敏感的. 2. 在#符号右面的内容 ...

  6. 简学Python第七章__class面向对象高级用法与反射

    Python第七章__class面向对象高级用法与反射 欢迎加入Linux_Python学习群  群号:478616847 目录: Python中关于oop的常用术语 类的特殊方法 元类 反射 一.P ...

  7. 笔记|《简明Python教程》:编程小白的第一本python入门书

    <简明Python教程>这本书是初级的Python入门教材,初级内容基本覆盖,对高级内容没有做深入纠结.适合刚接触Python的新手,行文比较简洁轻松,读起来也比较顺畅. 下面是我根据各个 ...

  8. Python第七天 函数 函数参数 函数里的变量 函数返回值 多类型传值 函数递归调用 匿名函数 内置函数

    Python第七天   函数  函数参数   函数里的变量   函数返回值  多类型传值     函数递归调用   匿名函数   内置函数 目录 Pycharm使用技巧(转载) Python第一天   ...

  9. 学习笔记《简明python教程》

    学习笔记<简明python教程> 体会:言简意赅,很适合新手入门 2018年3月14日21:45:59 1.global 语句 在不使用 global 语句的情况下,不可能为一个定义于函数 ...

随机推荐

  1. DAO,SERVICE

  2. 装饰器( decorate )

    装饰器分步解释-形成过程: #-*- coding: UTF-8 -*- #示例1: def deco(p_args): def pack(): print('haha,i am deco fun') ...

  3. C# 托管非托管资源释放

    1.C#几乎所有对象都为托管对象,不同点是有的对象封装了非托管资源. 2.C#大部分对象在进行垃圾回收时都可以回收,包括非托管资源,因为非托管资源都已经通过C#类进行了封装,会将非托管资源的释放放在析 ...

  4. 乘风破浪:LeetCode真题_020_Valid Parentheses

    乘风破浪:LeetCode真题_020_Valid Parentheses 一.前言 下面开始堆栈方面的问题了,堆栈的操作基本上有压栈,出栈,判断栈空等等,虽然很简单,但是非常有意义. 二.Valid ...

  5. JMeter中文版用户手册

    1.1 简介 使用JMeter通常会有以下步骤: 1.1.1 创建测试计划 首先,运行JMeter图形化界面. 然后在文件菜单中选择Templates…->Recording,通过浏览器录制We ...

  6. 一次失败的尝试hdfs的java客户端编写(在linux下使用eclipse)

    一次失败的尝试hdfs的java客户端编写(在linux下使用eclipse) 给centOS安装图形界面 GNOME桌面环境 https://blog.csdn.net/wh211212/artic ...

  7. C++课堂作业二之反转链表

    1问题链接: https://www.patest.cn/contests/pat-b-practise/1025 2解题想法: 这题原来用数组打过,现在是想保留暂存数据的数组,然后按顺序提取出来到创 ...

  8. 捡了一个非常淫荡的PHP后门,给跪了

    <?php unlink($_SERVER['SCRIPT_FILENAME']); ignore_user_abort(true); set_time_limit(0); $remote_fi ...

  9. C语言顺序表的实现

    今天本来想写段代码练练手,想法挺好结果,栽了个大跟头,在这个错误上徘徊了4个小时才解决,现在分享出来,给大家提个醒,先贴上代码: /********************************** ...

  10. BZOJ 1491 社交网络 Floyd 最短路的数目

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1491 题目大意: 见链接 思路: 直接用floyd算法求最短路,同时更新最短路的数目即 ...