Python第五课(字典)

时间:2022-07-05 04:36:22

字典

  序列这种数据结构是通过序号来访问调用元素集合中的值。但日常生活中的有些对象,两个对象之间存在某种关联关系。比如说电话号码属于某个人,电话号码和人之间就有属于的关系,想根据人的姓名来查找出电话号码,使用序列就不是特别的方便。这种情况下如果能够使用人的名字来进行查询就方便的多了,字典就是一种通过名字来访问调用值的数据结构。字典是python的一种映射类型。字典中的值没有特殊的顺序。

  • 创建和使用字典

  字典由键值对组成,使用大括号括起来。键值对使用“键:值”的格式作为一个整体被包含在大括号中。

  创建一个字典:name={‘lufei’:00000,‘suolong’:00001}

  调用字典中中的键值:name[‘lufei’]

  • dict函数

  和list函数、tuple函数相似,dict函数可以通过其他字典(映射)或者(键,值)对的序列建立字典。也可以通过关键字来建立字典。

1 >>> name=[('lufei',0),('suolong',1)]
2 >>> a=dict(name)         #通过包含键值对的序列建立字典
3 >>> a
4 {'lufei': 0, 'suolong': 1}
5 >>> b=dict(name='lufei',agg=19)   #通过关键字建立字典
6 >>> b
7 {'name': 'lufei', 'agg': 19}

 

  • 字典的基本操作

  1.len(d)返回字典d中键值对的数量

  2.d[k]返回字典d中关联到键d的值

  3.d[k]=v将值v关联到键k上

  4.del d[k]删除键位k的键值对

  5.k in d成员资格函数,判断字典d中是否含有键k

  • 字典于序列的区别

  1.序列中值对应的是序号,再序列中不能给不存在的序号赋值;字典中值对应的是键,字典中可以给不存在的键赋值,赋值后字典自动创建新的键值项;

  2.成员资格,序列使用成员资格函数判断的是某个值是否存在于序列中;字典使用成员资格函数判断的是某个键是否存在于字典中。

  • 字典的格式化字符串

  在学习字符串时学习了如何用格式化字符串对元组进行格式化,同样使用格式化字符串也可以对字典的值进行格式化处理

  在格式化操作符(%)后面跟字典的键并使用小括号括起来,后面再正常使用其他说明元素。结果会使用字典中键关联的值替换这部分内容。使用字典不需要特意的去注意值得顺序,在这点上来说是比使用元组更加方便的。

  • 字典方法

  1.clear

  清除字典中所有的项,clear方法在原位置操作,且不返回任何值

1 >>> a={'lufei':0,'suolong':1}
2 >>> b=a              #将字典的内存地址赋值给b
3 >>> name=a.clear()   #字典a调用clear方法,并将结果返回的值赋值给变量name
4 >>> b                #字典b所有项也被清除了,说明a的clear是在内存原位置进行的清除操作
5 {}
6 >>> name
7 >>> print(name)      #打印name的值为None说明方法clear不返回任何值
8 None
1 >>> a={'lufei':0,'suolong':1}
2 >>> b=a
3 >>> a={}     #这里是这段代码与上面一段代码唯一不同的。说明赋值语句是在内存中重新分配一片空间创建一个空字典并赋值给了变量a,而原来内存中的那个字典并没有被删除
4 >>> b
5 {'lufei': 0, 'suolong': 1}

  2.copy

  copy方法返回一个具有相同键值对的新字典。

 1 >>> a={'lufei':'cap','haizei':['suolong','namei','qiaoba']}
 2 >>> b=a.copy()                                              #字典a调用copy方法,并将返回的值赋值给b
 3 >>> b
 4 {'lufei': 'cap', 'haizei': ['suolong', 'namei', 'qiaoba']}  #看到结果字典b和a有一模一样的键值对
 5 >>> a['lufei']='haha'                                       #修改字典a中键‘lufei’的值
 6 >>> a['haizei'].remove('namei')                             #修改字典a中键‘haizei’的值
 7 >>> a
 8 {'lufei': 'haha', 'haizei': ['suolong', 'qiaoba']}          #第一次修改仅a发生了变化,b还是copy后的值
 9 >>> b
10 {'lufei': 'cap', 'haizei': ['suolong', 'qiaoba']}           #第二次修改字典b也发生了变化

  为什么会这样?同样是对原来的字典a做了操作,为什么赋值操作在copy得到的b中没有同步修改,对作为键值得列表的修改同步了?这是因为赋值操作和列表的部分方法在内存中的处理方法不同。赋值是重新开辟一块地址空间存放新的值并把值赋给需要的变量,而不需要的变量还是指向原来的值。而刚才的列表的remove操作是在列表的原位置进行移除元素,也就是说两个变量都是指向的位置a上的值,通过其中一个变量来对a的值进行了修改,两个变量再去访问位置a时,结果是一样的。

  有了弄清楚copy后赋值和修改这个过程在内存中的变化介绍一个函数id,id函数返回变量的值在内存中的地址

 1 >>> a={'lufei':'cap','haizei':['suolong','namei','qiaoba']}   #创建字典a
 2 >>> b=a.copy()            #copy字典a然后赋值给变量b
 3 >>> id(a)
 4 2197092086792
 5 >>> id(b)
 6 2197096782344           #分别查看字典a和字典b在内存中的地址,地址不相同说明copy操作是在内存中开辟一片空间,并创建了一个和字典a一模一样的字典b
 7 >>> id(a['haizei'])
 8 2197096789128
 9 >>> id(b['haizei'])
10 2197096789128           #查看字典a和字典b中的一个类型为列表的值在内存中的地址,地址相同说明了字典和字典b中的这个值指向内存中的同一个地址空间。如果这个列表改变那么a和b将同时改变
11 >>> a['lufei']='haha'
12 >>> a
13 {'haizei': ['suolong', 'namei', 'qiaoba'], 'lufei': 'haha'}
14 >>> b
15 {'haizei': ['suolong', 'namei', 'qiaoba'], 'lufei': 'cap'}
16 >>> id(a)
17 2197092086792
18 >>> id(b)
19 2197096782344
20 >>> a['haizei'].remove('namei')
21 >>> a
22 {'haizei': ['suolong', 'qiaoba'], 'lufei': 'haha'}
23 >>> b
24 {'haizei': ['suolong', 'qiaoba'], 'lufei': 'cap'}
25 >>> id(a)
26 2197092086792
27 >>> id(b)
28 2197096782344
29 >>> id(a['haizei'])
30 2197096789128
31 >>> id(b['haizei'])
32 2197096789128

   在浅copy中,对值进行替换操作时,可以仅在副本字典上修改,而原字典不变;但是当键关联的值是一个数据结构如列表,修改操作又是在原位置进行的操作时,在修改副本字典的同时原字典也会跟着被修改;然而在大多数情况下这种结果并不是我们想要的。我们用copy创建一个副本字典时,是想通过修改副本字典得到一个新的字典,同时还保存原始的字典。

  要实现这样的结果就要使用深copy——deepcopy。因为deepcopy是copy模块中的一个函数,在使用的时候需要使用import语句从模块中导入函数。

 1 >>> from copy import deepcopy          #从copy模块中导入deepcopy函数
 2 >>> name={'captain':'lufei','sailor':['suolong','namei','qiaoba']}
 3 >>> deepcopy_name=deepcopy(name)           #调用deepcopy函数创建字典name的副本deepcopy_name
 4 >>> deepcopy_name
 5 {'sailor': ['suolong', 'namei', 'qiaoba'], 'captain': 'lufei'}
 6 >>> deepcopy_name['captain']='haha'         #修改副本字典中的简单值
 7 >>> deepcopy_name['sailor'].remove('namei')         #修改副本字典中的列表中的值
 8 >>> name
 9 {'sailor': ['suolong', 'namei', 'qiaoba'], 'captain': 'lufei'}
10 >>> deepcopy_name
11 {'sailor': ['suolong', 'qiaoba'], 'captain': 'haha'}    #结果副本字典被修改,而原字典没有被修改

  3.fromkeys 

  通过给出的参数列表创建一个以参数列表中元素为键名称,默认值(默认为None)为键值的字典

1 >>> {}.fromkeys(('name','age'))
2 {'name': None, 'age': None}

  上面的描述并不是特别准确,从代码中可以看到。是先创建了一个空的字典,然后字典调用fromkeys方法,建立另外一个字典

1 >>> name={'a':'a','b':'b'}
2 >>> name.fromkeys(('c','d'))
3 {'c': None, 'd': None}
4 >>> name
5 {'b': 'b', 'a': 'a'}

  fromkeys不是在原字典上添加参数中给出的键,而是使用参数中给出的键创建一个新的字典。

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

 

  使用dict函数不给参数可以创建一个空字典,那么dict函数本身就可以作为字典来调用fromkeys方法。

  4.get

  通过键名称查询字典中与键关联的值,get方法特别的是如果参数中给出键名称在字典中不存在,将返回一个默认值,这个值可以在参数中给出。

 1 >>> name={'name':'lufei','age':'19'}
 2 >>> name.get('name')
 3 'lufei'
 4 >>> a=name.get('job')
 5 >>> print(a)
 6 None
 7 >>> name
 8 {'name': 'lufei', 'age': '19'}
 9 >>> b=name.get('job','meiyou')
10 >>> b
11 'meiyou'

 

  5.has_key

  这个方法的效果和成员资格一样,在3.0后python不包含这个方法,所以这里不详细说明使用方法是dict.has_key(k),含义为判断字典dict中是否包含k键,若包含返回True,若不包含返回False。

  6.keys and iterkeys

  keys方法将字典中的键名称以列表方式返回,而iterkeys方法将字典中的键名称以迭代器方式返回。

1 >>> name
2 {'name': 'lufei', 'age': '19'}
3 >>> name.keys()
4 dict_keys(['name', 'age'])
5 >>> a=name.keys()
6 >>> a
7 dict_keys(['name', 'age'])

  这样的返回值目前还不明白有什么作用,iterkeys在明白迭代器时再做说明。

  7.pop

  在字典中pop方法通过给定键删除键值对并返回键对应的值。

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

  8.popitem

  在列表中pop方法用来删除列表的最后一个元素并返回这个元素的值。因为字典是无序的,没有“最后一个元素”,字典中popitem删除的键值对是随机的。

1 >>> name={'a':'a','b':'b','c':'c'}
2 >>> name.popitem()
3 ('c', 'c')
4 >>> name.popitem()
5 ('b', 'b')

  以上字典键值对数量较少,调用popitem方法的数量较少,给人一种删除的键值对是目前在显示的顺序用最后的一对键值对的感觉。

  9.setdefault

  setdefault方法是加强版的get方法。get是通过给定的键查询与键关联的值,如果键不存在则返回一个默认值(可以在参数中给出默认是None)。而setdefault方法是通过给定的键查询字典中键关联的值,如果键值不存在返回默认的值(可在参数中设置),并在字典中添加这个键值对。

 1 >>> name={'captain':'lufei','suolong':'namei'}
 2 >>> name.setdefault('captain')
 3 'lufei'
 4 >>> print(name.setdefault('xiangji'))
 5 None
 6 >>> name
 7 {'suolong': 'namei', 'xiangji': None, 'captain': 'lufei'}
 8 >>> name.setdefault('luobin','haha')
 9 'haha'
10 >>> name
11 {'suolong': 'namei', 'xiangji': None, 'captain': 'lufei', 'luobin': 'haha'}

 

   上面代码说明三点setdefault的用法:给出键,返回键关联的值;如果查询的键在字典中不存在则返回None值,并在字典中添加键值对;可以修改默认值None的值。

  10.update

  可以利用一个字典项更新另一个字典。键不存在则添加新键值对,如果存在相同的键则覆盖键值对。

 1 >>> name
 2 {'suolong': 'namei', 'xiangji': None, 'captain': 'lufei', 'luobin': 'haha'}
 3 >>> a={'haijun':'hehe'}
 4 >>> name.update(a)
 5 >>> name
 6 {'suolong': 'namei', 'xiangji': None, 'captain': 'lufei', 'luobin': 'haha', 'haijun': 'hehe'}
 7 >>> a['haijun']='chacha'
 8 >>> name.update(a)
 9 >>> name
10 {'suolong': 'namei', 'xiangji': None, 'haijun': 'chacha', 'captain': 'lufei', 'luobin': 'haha'}

 

   11.values and itervalues

  values是以列表的形式返回字典中的值,itervalues是以迭代器的形式返回列表中的值

1 >>> name
2 {'suolong': 'namei', 'xiangji': None, 'haijun': 'chacha', 'captain': 'lufei', 'luobin': 'haha'}
3 >>> name.values()
4 dict_values(['namei', None, 'chacha', 'lufei', 'haha'])