PYTHON 学习第五章 之 字典

字典的介绍

  本章介绍一种可通过名称来访问其各个值的数据机构。这种数据结构称为映射(mappeing)。字典是python中唯一的内置映射类型,其中的值不按顺序排序,而是存储在键下。键可以是数,字符串或元组(听到映射和键值对,我就联想到了map, 也是无序的,也是也是映射,也是键值对)。果然语言与语言之间都是相同的,万变不离其宗。

 

创建字典

  语法:dict ={k:v}

phoneBook ={'张三':'135123456','李四':'7895412123','王五':'422335455'}

  字典由键及其相应的值组成,这种键-值对称为项(Item)。在前面的示例中,键为名称,而值为电话号码。每个键和值中间以冒号(:)分割,项之间用逗号分割,而整个字典放在花括号内。同样也可以创建空字典 如:{}

 

函数 dict

  与list,tuple和str一样,dict其实根本就不是函数,而是一个类。

  可使用函数 dict 从其他映射(如其他字典)或键-值对序列创建字典。其中包含指定映射中的所有项。如果调用这个函数没有提供任何实参,将返回一个空字典。

d = dict();
print(d)
#运行结果
{}

  如果映射也是字典(毕竟字典是Python中唯一的内置映射类型),可不是用函数dict,而是使用字典方法copy,后续将介绍到。

  注意:必须为一对(两个)才有效,否则报错

list :

item =[['name','张三'],['age',18]]
d = dict(item);
print(d)
print(d['name'])

#运行结果
{'name': '张三', 'age': 18}
张三

错误示范 

  案例一:列表中给三个?好像拨错了( •̀ ω •́ )y

item =[['name','张三','xxx'],['age',18,'xxx']]
d = dict(item);
print(d)
print(d['name'])

#运行结果
Traceback (most recent call last):
  File "D:/develTools/PycharmProjects/project1/venv/Include/test3.py", line 3, in <module>
    d = dict(item);
ValueError: dictionary update sequence element #0 has length 3; 2 is required

  案例二:单数不行?2的倍数可以把?糟糕 也报错了 5555

item =[['name','张三','xxx','aaa'],['age',18,'xxx','aaa']]
d = dict(item);
print(d)
print(d['name'])

#运行结果
Traceback (most recent call last):
  File "D:/develTools/PycharmProjects/project1/venv/Include/test3.py", line 3, in <module>
    d = dict(item);
ValueError: dictionary update sequence element #0 has length 4; 2 is required

案例五: 这样同样也是不行的,

item =[['name','张三','xxx','aaa']]
d = dict(item);
print(d)
print(d['name'])

#运行结果
Traceback (most recent call last):
  File "D:/develTools/PycharmProjects/project1/venv/Include/test3.py", line 3, in <module>
    d = dict(item);
ValueError: dictionary update sequence element #0 has length 4; 2 is required

  案例六:这样是没有问题的。

item =[['name','张三']]
d = dict(item);
print(d)
print(d['name'])

#运行结果
{'name': '张三'}
张三

  描述能力不行,雷我都趟完了,测试总结:只有单个列表中为是两个才可以,

tuple:  就不演示错误示范了,结果肯定和上面一样

item =(('name','张三'),('age',18))
d = dict(item);
print(d)
print(d['name'])

#运行结果
{'name': '张三', 'age': 18}
张三

  这样也是可以的

item =[('name','张三'),('age',18)]
d = dict(item);
print(d)
print(d['name'])
#运行结果
{'name': '张三', 'age': 18}
张三

 

基本的字典操作

  字典的基本行为在很多方面都类似于序列

  • len(d):返回字典d包含的项 (键-值对)数。
  • d[k]返回与键k相关联的值。
  • d[k]=v 将值v关联到键k
  • del d[k] 删除键为k的项
  • k in d 检查字典d 是否包含键为k的项

  虽然字典和列表有多个相同之处,但也有一些重要的不同之处。

  • 键的类型:字典中的键可以为整数,但非必须为整数。字典中的键可以是任何不可变的类型,如浮点数(实数)、字符串或数组
  • 自然添加:即便是字典中原本没有键,也可以给它赋值,这将在字典中创建一个新项。然而,如果不使用append或其他类似的方法,就不能给列表中没有元素赋值。
    d = dict();
    print(d)
    d['name']='张三'
    print(d)
    
    #运行结果’
    {}
    {'name': '张三'}
  • 成员资格:表示k in d(其中d是一个字典)查找的是键而不是值,而表达式v in l(其中l是一个列表)查找的是值而不是索引。这看似太不一致,习惯之后就好了。毕竟如果字典包含指定的键,检查相应的值就很容易。
    d = dict();
    d['name']='张三'
    d['sex']=''
    
    print('name' in d)
    #运行结果
    True

  相比检查列表是否包含指定的值,检查字典是否包含指定的键的效率更高。数据结构越大,效率差距就越大。

将字符串设置格式功能用于字典

  可使用字符串格式设置功能来设置值的格式,这些值是作为命名或非命名参数提过给format的。在有些情况,通过在字典中存储一系列命名的值,可让格式设置更容易些。例如,可在字典中包含各种信息,这样只需要在格式字符串中提取所需的信息即可。为此必须使用format_map来指出你将通过一个映射来提供所需的信息。

  案例:

person={'name':'张三','sex':'','age':18}
info='姓名:{name},性别:{sex},年龄:{age}'.format_map(person)
print(info)

#运行结果
姓名:张三,性别:男,年龄:18

  form 和 form_map 有什么区别?请看format 输出案例

person={'name':'张三','sex':'','age':18}
info='姓名:{pe[name]},性别:{pe[sex]},年龄:{pe[age]}'.format(pe=person)
print(info)

#运行结果
姓名:张三,性别:男,年龄:18

 

字典方法:

  clear:删除所有的字典项,这种操作属于就地执行(就像list.sort),因此返回为None

person={'name':'张三','sex':'','age':18}
person.clear()
print(person)

#运行结果
{}

  copy:返回一个新字典,其包含的键-值对与原来的字典相同(这个方法执行的是浅复制,因为值本身是原件,而非副本)。

  案例:

person1={'name':'张三','sex':'','age':18,'hobby':['篮球','rap','音乐']}
#复制一份给 person2
person2=person1.copy()
#这里是替换而不是修改
person1['name']='李四'
person2['name']='王五'
print(person1)
print(person2)
#运行结果
{'name': '李四', 'sex': '', 'age': 18, 'hobby': ['篮球', 'rap', '音乐']}
{'name': '王五', 'sex': '', 'age': 18, 'hobby': ['篮球', 'rap', '音乐']}

  上面的案例只是将 每个用户的name 进行替换了,好像结果没啥问题?那为什么说是原件呢?原来当替换副本中的值时,原件不受影响。然而,如果修改副本中的值(就地修改不是替换),原件就会受到影响。

  案例:

person1={'name':'张三','sex':'','age':18,'hobby':['篮球','rap','音乐']}
#复制一份给 person2
person2=person1.copy()
#这里是替换而不是修改
person1['hobby'].remove('篮球')
person2['name']='王五'
print(person1)
print(person2)
#运行结果
{'name': '张三', 'sex': '', 'age': 18, 'hobby': ['rap', '音乐']}
{'name': '王五', 'sex': '', 'age': 18, 'hobby': ['rap', '音乐']}

  ???person2的 hobby 也居然被删除了,为了解决这种问题,那么就需要深复制,使用copy中的 deepcopy 函数

  需要引入 from copy import deepcopy

from copy import  deepcopy

person1={'name':'张三','sex':'','age':18,'hobby':['篮球','rap','音乐']}
#复制一份给 person2
person2=deepcopy(person1)
#这里是替换而不是修改
person1['hobby'].remove('篮球')
person2['name']='王五'
print(person1)
print(person2)
#运行结果
{'name': '张三', 'sex': '', 'age': 18, 'hobby': ['rap', '音乐']}
{'name': '王五', 'sex': '', 'age': 18, 'hobby': ['篮球', 'rap', '音乐']}

  fromkeys:创建一个新字典,其中包含指定的键,且每个键对应的值都是None(这个我感觉有点多余,既然不指定值,我还定义它干嘛?)

person=dict.fromkeys({'name','sex','age'})
print(person)
#运行结果
{'sex': None, 'age': None, 'name': None}

  若不想展示 None 可以指定特定的值(真的是特定的值

person=dict.fromkeys({'name','sex','age'},'特定的值')
print(person)
#运行结果
{'age': '特定的值', 'name': '特定的值', 'sex': '特定的值'}

  get:获得字典中某个元素值

person={'name':'张三','sex':'','age':18,'hobby':['篮球','rap','音乐']}
print(person.get('name'))
#运行结果
张三

  get 函数 和之前用到得 dict['name'] 是一样的,既然存在就有他的道理,

  案例:访问一个不存在的元素时,看看他们会有什么不同?

 正常的情况下:
person={'name':'张三','sex':'','age':18,'hobby':['篮球','rap','音乐']}
print("person.get('name') 结果为:"+person.get('name'))
print("person['name'] 结果为:"+person['name'])
#运行结果
person.get('name') 结果为:张三
person['name'] 结果为:张三

  错误的情况下:...好尴尬,报错了

person={'name':'张三','sex':'','age':18,'hobby':['篮球','rap','音乐']}
print("person.get('name') 结果为:"+str(person.get('xxx'))) 
print("person['name'] 结果为:"+str(person['xxx']))

#运行结果?
person.get('name') 结果为:None
#----------------------------------- 

Traceback (most recent call last): File "D:/develTools/PycharmProjects/project1/venv/Include/test3.py", line 3, in <module> print("person['name'] 结果为:"+person['xxx']) KeyError: 'xxx'

  由此看出,使用 dict['name'] 当name 不存在时,则会抛出异常,dict.get('name') 会抛出Node,若你不想返回Node ,也是可以指定的。如

  get('key','异常时消息打印')

person={'name':'张三','sex':'','age':18,'hobby':['篮球','rap','音乐']}
print("person['name'] 结果为:"+person.get("xxx",'哎呀,你居然找不到'))

#运行结果
person['name'] 结果为:哎呀,你居然找不到

  比起上面的报错 ,这样是不是更优雅?正常的情况是不会打印后面的信息的

person={'name':'张三','sex':'','age':18,'hobby':['篮球','rap','音乐']}
print("person['name'] 结果为:"+person.get("name",'哎呀,你居然找不到'))
#运行结果
person['name'] 结果为:张三

  items:返回一个包含所有字典项的列表,每个元素都为(key,value)的形式。但是字典项在列表中的顺序是不确定的?

  这里打个问号,我运行了好几遍顺序都是一致的,刚开始我以为数据少,然后还加了一些,无论多少遍还还是一致的。可能书本的python版本比较老吧,新版本已经修复这个问题了(所以不要光看书,实践最重要)。

  items 返回值属于一种名为字典试图的特殊类型(我不是很明白,书本是这么说的,只有待以后接触更多python知识才会知晓),字典视图可用于迭代(就是能够遍历,意思是字典本身是不能遍历的?需要转为字典视图?)。

person={'name':'张三','sex':'','age':18,'hobby':['篮球','rap','音乐'],'sss1':'sss1','sss2':'sss2','sss3':'sss3','sss4':'sss4','sss5':'sss5'}
print(person.items())

#运行结果
dict_items([('name', '张三'), ('sex', ''), ('age', 18), ('hobby', ['篮球', 'rap', '音乐']), ('sss1', 'sss1'), ('sss2', 'sss2'), ('sss3', 'sss3'), ('sss4', 'sss4'), ('sss5', 'sss5')])

  keys:返回一个字典试图(又是字典试图,上面提到的),包含字典中所有的key

person={'name':'张三','sex':'','age':18,'hobby':['篮球','rap','音乐'],'sss1':'sss1','sss2':'sss2','sss3':'sss3','sss4':'sss4','sss5':'sss5'}
print(person.keys())

#运行结果
dict_keys(['name', 'sex', 'age', 'hobby', 'sss1', 'sss2', 'sss3', 'sss4', 'sss5'])

  pop:根据key删除字典中的 key-value,并返回所属key的值

person={'name':'张三','sex':'','age':18,'hobby':['篮球','rap','音乐'],'sss1':'sss1','sss2':'sss2','sss3':'sss3','sss4':'sss4','sss5':'sss5'}
print(person.pop('sss1'))
print(person)

#运行结果
删除key为sss1后value=:sss1
最终person里的数据结果:{'name': '张三', 'sex': '', 'age': 18, 'hobby': ['篮球', 'rap', '音乐'], 'sss2': 'sss2', 'sss3': 'sss3', 'sss4': 'sss4', 'sss5': 'sss5'}

  popitem:类似于 list.pop, 弹出列表中最后一个元素。如果你要高效的方式逐个删除并处理所有字典项,这个很有用,因为这样无需先获取key列表。

  书本上说 popitem 是随机删除 字典中的某个字典项(看到这句话时,我赶紧测试了下,运行几次后,还是没有这个问题),因为字典时没有顺序可言的。书本中也指出了若希望 popitem以可预测的顺序弹出字典项,请阅读collections中的OrderedDict类

person={'name':'张三','sex':'','age':18,'hobby':['篮球','rap','音乐'],'sss1':'sss1','sss2':'sss2','sss3':'sss3','sss4':'sss4','sss5':'sss5'}
print(person.popitem())

#运行结果
最后一个 字典项:('sss5', 'sss5')

  setdefault:这个很有意思,他的功能和 get函数类似。

  但是setdefault是具备添加功能的, 当字典中存在时,setdefault 返回  字典中 该key的value

person={'name':'张三','sex':'','age':18,'hobby':['篮球','rap','音乐']}
print(person.setdefault('name'))
#运行结果
张三

  但是当key不存在时,他会将这个字典项存入 字典中( value默认为 None),为了证明 setdefault函数 将 xxx 存入 到 person中。这里用 person['xxx'] 的形式获取 该 xxx 的值

person={'name':'张三','sex':'','age':18,'hobby':['篮球','rap','音乐']}
print(person.setdefault('xxx'))
#为了证明 setdefault函数 将  xxx 存入 到  person中。这里用 person['xxx'] 的形式获取 该 xxx 的值
print(person['xxx'])
#运行结果
None
None

  value 也是可以指定的

person={'name':'张三','sex':'','age':18,'hobby':['篮球','rap','音乐']}
print(person.setdefault('xxx','N/A'))
#为了证明 setdefault函数 将  xxx 存入 到  person中。这里用 person['xxx'] 的形式获取 该 xxx 的值
print(person['xxx'])
#运行结果
N/A
N/A

  update:使用一个字典中的项更新另一个字典

  注意:不要key重复

person={'name':'张三','sex':'','age':18,'hobby':['篮球','rap','音乐']}

school={'school':'xxx希望小学','className':'一年级一班'}

person.update(school)

print(person)

#运行结果
{'name': '张三', 'sex': '', 'age': 18, 'hobby': ['篮球', 'rap', '音乐'], 'school': 'xxx希望小学', 'className': '一年级一班'}

  values:返回一个由字典中的值所组成的字典试图

  不同于keys函数,values 是可以包含重复的。

   案例:张三的年龄我为18,考试得分也是18

person={'name':'张三','sex':'','age':18,'hobby':['篮球','rap','音乐'],'score':18}

print(person.values())

#运行结果
dict_values(['张三', '', 18, ['篮球', 'rap', '音乐'], 18])

 

笔后语录:

  目前为止,python教学视频进度一点没变,还是在面向对象(深入面向对象)部分,下部分该学习 包相关的知识了(我觉得不应该急着去看视频)。但是我停下来了,买了一本python基础书,从头开始看python,书本内容我也看到面向对象,这篇博客园这也是第四章的全部内容。我目前博客里所有有关python的文章都是按照书本中的知识案例点来总结的。所有的案例也是我一个个敲出来贴到博客中。有些时候我按照书本中的案例运行时,我也会产生一些其他想法,我就会尝试另外一种运行方式,并将结果写到博客中。我写这些博客的目的不是为了装X,我觉得完全没必要,我本身是从事java开发的工作,学习python也只是我闲暇的时光去学习(主要是太多人学习,我觉得多多少少要接触一点)。这个行业压力太大了,随时觉得自己要被淘汰。

  那我又干嘛写呢?本身就没打算靠python挣钱吃饭,大部分时间还是关注到java中比较多,所以学完长时间不用,就很容易忘,好记性,不如烂笔头。把学习的过程记录下来,主要是加强记忆,然后学习完某种技术后,再回头看看自己的博客真的有种成就感。以前我不懂写博客(内容没有营养,杂乱无章),翻看我以前博客(跟屎一样)没有归类,没有系统化,所以以后的博客内容尽量让它丰富起来。

  突然谈到写博客,是因为,我害怕的我的内容误导你,不过请放心,所有代码我都是经过测试了的。以后接触到更多知识后,我会补充到相对应的博客中,不仅仅是python。

  要是内容有什么不对,请下方留言。

 

 

 

 

posted @ 2019-11-09 20:26  不朽_张  阅读(407)  评论(0)    收藏  举报