《Python基础教程》第四章–读书笔记
admin
2023-07-31 01:44:28
0

第四章: 字典-当索引不好用时

在本章,将学到通过名字来引用值的数据结构。这种类型的数据结构成为映射(mapping)。

字典是python中唯一内建的映射类型。

字典中的值并没有特殊的顺序,但都是存储在一个特定的键(key)下。键可以是数字、字符串甚至是元祖。

字典的使用

某些情况下,字典比列表更加适用,比如:

  • 标示一个棋盘的状态,每个键都是由坐标组成的元祖;

  • 存储文件修改时间,用文件名作为键;

  • 数字电话/地址簿

>>>010
8

这并不是10,因为,八进制数字均是以0为开头的。
教训就是:电话号码(以及其他可能以0开头的数字)应该表示为数字字符串,而不是整数。

创建和使用字典

字典由多个键与其对应的值构成的键-值对组成(我们也把键-值对称为项)。

**注:字典中的键是唯一的(其他类型的映射也是如此),而值并不是唯一。

>>>a={\'a\':1,\'b\':2,\'a\':3}
>>>a
{\'a\':3,\'b\':2}

dict函数

可以用dict函数(dict函数不是真正的函数,它是个类型,就像list,tuple,str一样)。通过其他映射(比如其他字典)或者(键,值)对的序列建立字典。

>>>items=[(\'name\',\'Michael\'),(\'age\',42)]
>>>d=dict(items)
>>>d
{\'age\':42,\'name\':\'Michael\'}

dict函数也可以通过关键字参数来创建字典。

>>>d = dict(name=\'Micahel\',age=42)
>>>d
{age:42,\'name\':\'Michael\'}

基本字典操作

字典的基本行为在很多方面与序列(sequence)类似:

  • len(d)返回d中项(键-值对)的数量;

  • d[k]返回关联到键k上的值;

  • del d[k]删除键为k的项

  • k in d检查d中是否含有键为k的项

尽管字典和列表有很多特性相同,但也有下面的一些重要区别:

  • 键类型:字典的键不一定是整型数据(但也可以是),键可以是任意的不可变类型,比如浮点型(实型)、字符串或者元祖。

  • 自动添加:即使键起初在字典中不存在,也可以为他赋值,这样字典就会建立新的项。而(在不使用append方法或者其他类似操作的情况下)不能将值关联到列表范围之外的索引上。

  • 成员资格:表达式k in d(d为字典)查找的是键,而不是值。表达式v in L (L为列表)则用来查找值,而不是索引。

第一点——键可以是任意不可变类型——是字典最强大的地方。

>>>x=[]
>>>x[42]=\'michael\'
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
 in ()
      1 x=[]
----> 2 x[42]=\'michael\'
 
IndexError: list assignment index out of range
>>>x={}
>>>x[42]=\'Michael\'
>>>x
{42:\'Michael\'}

字典的格式化字符串

在每个转换说明符(conversion specifier)中的%字符后面,可以加上键(用圆括号括起来的),后面再跟上其他说明元素。

>>>phonebook={\'michael\':\'123\',\'hh\':234}
>>>\"michaelis phone number is %(michael)s.\"%phonebook
\'michaelis phone number is 123\'

这类字符串格式化在模板系统中非常有用。

字典方法

clear

clear方法清除字典中所有的项。 这个原地操作(类似list.sort),所以无返回值(或者说返回None)。
为什么这个方法有用呢?考虑一下两种情况:
栗子1:

>>>x = {}
>>>y = x
>>>x[\'key\']=\'value\'
>>>y
{\'key\':\'value\'}
>>>x = {}
>>>y
{\'key\':\'value\'}

栗子2:

>>>x = {}
>>>y = x
>>>x[\'key\']=\'value\'
>>>y
>>>x.clear()
>>>y
{}

其实归根结底,记住clear方法跟sort方法一样,没有返回值。

copy

copy方法返回一个觉有相同键-值对的新字典(这个方法实现的是浅复制(shallow copy),因为值本身就是相同的,而不是副本)。

>>>x={\'a\':1,\'b\':[1,2,3]}
>>>y=x.copy()
>>>x[\'a\']=0
>>>print x
{\'a\': 0, \'b\': [1, 2, 3]}
>>>print y
{\'a\': 1, \'b\': [1, 2, 3]}
>>>y[\'b\'].append(4)
>>>print x
{\'a\': 0, \'b\': [1, 2, 3, 4]}
>>>print y
{\'a\': 1, \'b\': [1, 2, 3, 4]}

通过上图的执行顺序可以看出,对于字典中的值,他们是分立的,互相不影响;但是,字典中值是引用型的,他们就会互相影响。从上面的动态图也可以猜想,浅复制并不是完全复制,y并不是完全和x分隔的副本。原始字典中值存在例如列表这样的引用型传递的,那么,y中存储的值就是引用型传递的结果,存储的是和x中引用型值一样。

反正自己这么理解,可以解释通得到的结果。

通过这么理解,写了另外一个栗子:

>>>x={\'a\':1,\'b\':[1,2,3]}
>>>y=x.copy()
>>>x[\'a\']=0
>>>print x
{\'a\': 0, \'b\': [1, 2, 3]}
>>>print y
{\'a\': 1, \'b\': [1, 2, 3]}
>>>y[\'b\']=[\'m\',\'n\']
>>>print x
{\'a\': 0, \'b\': [1, 2, 3, 4]}
>>>print y
{\'a\': 1, \'b\': [\'m\',\'n\']}

避免出现这样问题的一种方法就是深复制(deep copy),复制其包含的所有值。可以使用copy模板的deepcopy函数来完成。就不举例了。

浅复制参考文档:

  • 深入Python(4):深拷贝和浅拷贝

  • 官方:copy — Shallow and deep copy operations

fromkeys

fromkeys方法使用给定的键建立新的字典,每个键都对应一个默认的值None。

>>>{}.fromkeys([\'name\',\'age\'])
{\'age\':None,\'name\':None}

此外,还可以直接在dict上面调用该方法,前面讲过,dict是所有字典的类型。

>>>dict.fromkeys([\'name\',\'age\'])
{\'age\':None,\'name\':None}

如果不想使用None作为默认值,也可以自己提供默认值。

>>>dict.fromkeys([\'name\',\'age\'],\'(unknown)\')
{\'age\': \'(unknown)\', \'name\': \'(unknown)\'}

get

get方法是个更宽松的访问字典项的方法。一般说来,如果试图访问字典中不存在的项时会出错:

>>>d = {}
>>>print d[\'name\']
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
 in ()
      1 d={}
----> 2 print d[\'name\']
 
KeyError: \'name\'
>>>print d.get(\'name\')    #用get方法就不会
None
>>>d.get(\'name\',\'N/A\')    #还可以自定义默认值
\'N/A\'

haskey

haskey方法可以检查字典中是否含有特定的键。表达式d.haskey(k)相当于表达式k in d。使用哪个方式取决于个人喜好。python3.0中不包括这个函数。

items和iteritems

items方法将字典所有的项以列表方式返回,列表中的每一项都表示为(键,值)对的形式。

>>>d={\'title\':\'test\',\'name\':\'michael\',\'age\':24}
>>>d.items()
[(\'age\', 24), (\'name\', \'michael\'), (\'title\', \'test\')]

itritems方法的作用大致相同,但是会返回一个迭代器对象而不是列表:

>>>it = d.iteritems()
>>>it

>>>list(it)
[(\'age\', 24), (\'name\', \'michael\'), (\'title\', \'test\')]

在很多情况下,iteritems方法效果会更加高(尤其是想要迭代结果的情况下)。参考第九章。

keys和iterkeys

keys方法将字典中的键以列表形式返回。iterkeys则返回针对键的迭代器。

pop

pop方法用来获得对应于给定键的值,然后将这个键-值对从字典中移除。

>>>d = {\'a\':1,\'b\':2}
>>>d.pop(\'a\')
1
>>>d
{\'b\':2}

popitem

popitem方法类似于list.pop,后者会弹出列表的最后一个元素。但不同的是,popitem弹出随机的项,因为字典并没有”最后的元素\”或者其他有顺序的概念!!!

若想要一个接一个地移除并处理项,这个方法就非常有效了(因为不用首先获取键的列表)。

>>>d = {\'a\':1,\'b\':2}
>>>d.popitem()
(\'a\', 1)
>>>d
{\'b\':2}

setdefault

setfault方法在某种程度上类似于get方法,能够获得给定键相关联的值。不同的地方时,setdefault还能在没有对应键存在的情况下,设定相应的键。

>>>d={}
>>>d.setdefault(\'name\',\'N/A\')    #如果对应键存在,那么久返回键关联的值。默认是可选的。
\'N/A\'

update

update方法可以利用一个字典项更新另外一个字典。

>>>a={\'x\':1,\'y\':2,\'z\':3}
>>>b={\'x\':0}
>>>a.update(b)
>>>a
{\'x\':0,\'y\':2,\'z\':3}

如果有相同的键,则会进行覆盖。如果没有相同键,则会添加!

values和itervalus

values方法以列表的形式返回字典中的值(itervalues返回值的迭代器)

本章小结

  • 映射:映射可以使用任意不可变对象标识元素。最常用的类型是字符串和元祖。python唯一内建的映射类型是字典。

  • 浅复制(shallow copy)和深复制(deepcopy):本来是比较小的知识点,基础教程中也没有深入讲解一下为何是这样的结果,由于没太看明白,查资料,还是有收获的!希望以后能有资料更深入了解一下~

    • 深入Python(4):深拷贝和浅拷贝

    • 官方:copy — Shallow and deep copy operations

    • stackoverflow浅复制问题

元旦节日,教研室人气不高,反倒是感觉挺好~加油~坚持下去!

相关内容

热门资讯

Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
Apache Doris 2.... 亲爱的社区小伙伴们,我们很高兴地向大家宣布,Apache Doris 2.0.0 版本已于...
项目管理和工程管理的区别 项目管理 项目管理,顾名思义就是专注于开发和完成项目的管理,以实现目标并满足成功标准和项目要求。 工...