Python学习笔记(4)-数据类型之字典

为什么要使用字典

引出字典

当一系列的值组合成数据结构,并通过编号来访问各个值的时候,可以使用列表。而在另外一种情况下,例如当我们不想使用通过编号来访问其值的数据结构,而是想用一种通过名称来访问其值的数据结构,这种数据结构就称为映射(mapping)。在Python中,字典(dict)是唯一的内置映射类型,其值不按顺序排列,而是储存在下,这个可以是数字、字符串或元组。

字典的用途

从字典这个名称来看,它的功能就是在于找到某个特定的单词(在Python的字典数据结构中,这个单词叫键key),从而获得其定义(Python中叫)。

我们来看一个案例,例如我们有以下的名单:

1
names = ['Alice', 'Beth', 'Cecil', 'Dee-Dee', 'Earl']

如果我们要创建一个小数据库来储存这些人的电话号码,如何实现?在学习字典这个数据结构前,我们可能会想到使用列表,创建一个列表储存他们的电话号码,如下所示:

1
numbers = ['2341', '9102','3158','0142', '5551']

当我们要查询Ceil的电话号码时,可以按下面的代码实现:

1
numbers[names.index('Cecil')]

完整的运行结果如下所示:

1
2
3
4
5
>>> names = ['Alice', 'Beth', 'Cecil', 'Dee-Dee', 'Earl']
>>> numbers = ['2341', '9102','3158','0142', '5551']
>>>
>>> numbers[names.index('Cecil')]
'3158'

但是这种方法比较麻烦,事实上,如果我们直接按照姓名来查找电话号码就方便了,如下所示:

1
2
phonebook = {'Alice':'2341','Beth':'9102', 'Cecil':'3258'}
phonebook['Cecil']

运行结果如下所示:

1
2
3
>>> phonebook = {'Alice':'2341','Beth':'9102', 'Cecil':'3258'}
>>> phonebook['Cecil']
'3258'

其中phonebook这个变量的类型就是字典

字典的定义

字典包括一系列的索引,不过就已经不叫索引了,而是叫键,然后还对应着一个值,叫键值。每个键对应着各自的一个单独的键值。这种键和键值的对应关系也叫键值对,有时候也叫项。其中,“键:值”元素的无序可变序列,字典中的每个元素包括“键”和“值”两部分,表示一种映射或对应关系,也称为关联数组。定义字典时,每个元素的“键”和“值”用冒号分隔,不同元素之间用逗号分隔,所有的元素放在一对大括号中。字典就像是一个列表一样,但更加泛化了,是列表概念的推广。在列表里面,索引必须是整数;而在字典里面,你可以用几乎任何类型来做索引了。用数学语言来说,一个字典就代表了从键到键值的一种映射关系,所以你也可以说每个键映射到一个键值。举例来说,我们可以建立一个从英语单词映射到西班牙语单词的字典,这样键和简直就都是字符串了。

建立字典

使用dict()函数

dict这个函数创建一个没有项目的空字典,如下所示:

1
2
3
>>> eng2sp = dict()
>>> eng2sp
{}

其中,大括号代表了一个空字典,要在字典里添加项(项是指字典的键与值的对应关系,也叫键值对),可以使用方括号,如下所示:

1
2
3
>>> eng2sp['one'] = 'uno'
>>> eng2sp
{'one': 'uno'}

也可以采用直接给定的“键:值”来创建字典,如下所示:

1
2
3
>>> d = dict(name = 'Dong', age = 37)
>>> print(d)
{'name': 'Dong', 'age': 37}

通过dict转化为字典

如下所示:

1
2
3
4
keys = ['a','b','c','d']
values = [1,2,3,4]
dictionary = dict(zip(keys,values))
print(dictionary)

运行结果如下所示:

1
2
3
4
5
>>> keys = ['a','b','c','d']
>>> values = [1,2,3,4]
>>> dictionary = dict(zip(keys,values))
>>> print(dictionary)
{'a': 1, 'b': 2, 'c': 3, 'd': 4}

通过fromkeys()创建新字典

给定内容为“键”,创建“值”为空的字典:

1
2
adict = dict.fromkeys(['name','age','sex'])
print(adict)

运行结果如下所示:

1
2
3
>>> adict = dict.fromkeys(['name','age','sex'])
>>> print(adict)
{'name': None, 'age': None, 'sex': None}

fromkeys()方法用于创建一个新的字典,并以可迭代对象中的元素分别作为字典中的键,且所有键对应同一个值,默认为None。

如果不想使用默认值None,那么可以指定值,如下所示:

1
2
adict2 = dict.fromkeys(['name','age','sex'], '(UNKNOWN)')
print(adict2)

结果如下所示:

1
2
3
>>> adict2 = dict.fromkeys(['name','age','sex'], '(UNKNOWN)')
>>> print(adict2)
{'name': '(UNKNOWN)', 'age': '(UNKNOWN)', 'sex': '(UNKNOWN)'}

字典的修改

当以指定“键”为下标,并为字典元素赋值时,有两种含义:①若该“键”存在,则表示修改该“键”对应的值;②若该键不存在,则表示添加一个新的“键:值”,也就是添加一个新元素,如下所示:

1
2
3
4
5
6
7
>>> aDict ={'age':35, 'name':'Dong','sex':'male'}
>>> print(aDict)
{'age': 35, 'name': 'Dong', 'sex': 'male'}
>>> aDict['age'] = 38 #修改元素值
>>> aDict['address'] = 'SDIBT' # 添加新元素
>>> print(aDict)
{'age': 38, 'name': 'Dong', 'sex': 'male', 'address': 'SDIBT'}

添加字典——更新字典update()

update()方法可以将另一个字典的“键:值”一次性全部添加到当前的字典对象,如果两个字典中存在相同的“键”,则以另外一个字典中的“值”为准对当前字典进行更新,如下所示:

1
2
3
4
5
6
>>> aDict={'age':37, 'score':[98,97],'name':'Dong','sex':'male'}
>>> print(aDict.items())
dict_items([('age', 37), ('score', [98, 97]), ('name', 'Dong'), ('sex', 'male')])
>>> aDict.update({'a':97, 'age':39}) # 修改'age'键的值,同时添加新元素'a':97
>>> print(aDict)
{'age': 39, 'score': [98, 97], 'name': 'Dong', 'sex': 'male', 'a': 97}

删除字典del()

del可以删除整个字典,也可以删除字典中指定的元素,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
>>> aDict={'age':37, 'score':[98,97],'name':'Dong','sex':'male'}
>>> print(aDict)
{'age': 37, 'score': [98, 97], 'name': 'Dong', 'sex': 'male'}
>>> del aDict
>>> print(aDict)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'aDict' is not defined
>>> aDIct
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'aDIct' is not defined

删除字典pop()popitem()

(1)pop()方法删除字典给定键 key 所对应的值,返回值为被删除的值。key值必须给出。 否则,返回default值。

(2)popitem() 方法随机返回并删除字典中的一对键和值(一般删除末尾对)。

如果字典已经为空,却调用了此方法,就报出KeyError异常,如下所示:

1
2
3
4
5
6
7
>>> aDict={'age':37, 'score':[98,97],'name':'Dong','sex':'male'}
>>> aDict.popitem() # 弹出一个元素,如果是空字典,则会抛出异常
('sex', 'male')
>>> aDict.pop('age')
37
>>> print(aDict) # 弹出指定键对应的元素
{'score': [98, 97], 'name': 'Dong'}

随机删除字典元素dd.popitem()

dd.popitem()的功能是随机删除字典中的一个元素,并将所删除的值返回,运行结果如下所示:

1
2
3
4
5
>>> dd = {"name":"qiwsir","lang":"python","web":"www.itdiffer.com"}
>>> print(dd.popitem())
('web', 'www.itdiffer.com')
>>> print(dd)
{'name': 'qiwsir', 'lang': 'python'}

字典的清除clear()

字典的清除使用clear()方法,如下所示:

1
2
3
4
5
6
>>> a = {"name":"qiwsir"}
>>> print(a)
{'name': 'qiwsir'}
>>> a.clear()
>>> print(a)
{}

清除与删除是两种不同的操作,如下所示:

1
2
3
4
5
6
7
8
9
10
11
>>> a = {"name":"qiwsir"}
>>> print(a)
{'name': 'qiwsir'}
>>> a.clear()
>>> print(a)
{}
>>> del a
>>> print(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined

访问项(键:值)

字典中的项没有顺序,因此也没有索引,但可以通过键来直接查找键值,如下所示:

1
2
3
4
5
6
7
8
9
>>> eng2sp = {'one': 'uno', 'three': 'tres', 'two': 'dose'}
>>> eng2sp['three'] = 'tres'
>>> eng2sp['two'] = 'dose'
>>> eng2sp
{'one': 'uno', 'three': 'tres', 'two': 'dose'}
>>> eng2sp
{'one': 'uno', 'three': 'tres', 'two': 'dose}
>>> eng2sp['one']
'uno'

字典的”键(key)”不能是可变类型,也就是说不能是列表,但可以是元组,整数,字符串。

访问值get()

get()函数用法:get() 函数返回指定键的值,如果值不在字典中返回默认值。

1
2
3
4
5
>>> aDict={'age':37, 'score':[98,97],'name':'Dong','sex':'male'}
>>> aDict.get('age') # 如果字典中存在该"键",则返回对应的值
37
>>> aDict.get('address','Not Exists') # 指定的"键"不存在,返回指定的默认值
'Not Exists'

访问值setdefault()

此方法用于返回指定“键”对应的“值”,如果字典中不存在该“键”,就添加一个新元素,并设置该键对应的值,如下所示:

1
2
3
4
5
>>> aDict={'age':37, 'score':[98,97],'name':'Dong','sex':'male'}
>>> aDict.setdefault('address','SDIBT') # 添加新元素
'SDIBT'
>>> aDict
{'age': 37, 'score': [98, 97], 'name': 'Dong', 'sex': 'male', 'address': 'SDIBT'}

访问值遍历字典item()

对字典对象进行迭代时,默认是遍历字典的键,如果使用items()方法返回字典中的元素,即所有的项(项这里是指“键:值”对)。字典对象的keys()方法返回所有的值,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
>>> aDict={'age':37, 'score':[98,97],'name':'Dong','sex':'male'}
>>> for item in aDict:
... print(item)
...
age
score
name
sex
>>> for item in aDict.items():
... print(item)
...
('age', 37)
('score', [98, 97])
('name', 'Dong')
('sex', 'male')
>>> aDict.items()
dict_items([('age', 37), ('score', [98, 97]), ('name', 'Dong'), ('sex', 'male')])
>>> aDict.keys()
dict_keys(['age', 'score', 'name', 'sex'])
>>> aDict.values()
dict_values([37, [98, 97], 'Dong', 'male'])

同置函数对字典的处理

内置函数len(),max(),min(),sum(),sorted()以及成员测试运算符in也适用于字典对象,但默认作用于字典的“键”,若想作用于元素,即“键:值”对,则需要使用字典的对象items()方法,若作用于“值”,则需要使用valules()方法。

案例实战:字典应用

案例实战:字典应用
  下面的一段代码会生成包括1000个随机字符的字符串,然后统计每具字符的出现次数。

包解释:

  1. string:String模块包含许多有用的常量和类,以及一些不推荐的遗留函数,这些函数也可以作为字符串上的方法使用。此外,Python的内置字符串类支持序列类型(str、Unicode、list、tuple、byteArray、Buffer、xrange)中描述的序列类型方法,以及String方法部分中描述的特定字符串的方法。若要输出格式化字符串,可以使用模板字符串或字符串格式操作部分的%运算符。另外,有关基于正则表达式的字符串函数,请参见re模块。
  2. random:这个模块是用于实现各种分页的伪随机数生成器。对于整数来说,它可以从一个范围内进行均匀选择,对于序列来说,此模块中的有可以均匀选择一个元素的函数,以及生成一个随机排列的列表的耿发,以及用于不放回抽样的函数。

代码解释:

  1. ascii_letters是生成所有字母,从a-z和A-Z
  2. digits是生成所有数字0-9.
  3. punctuation生成标点符号
  4. random.choice随机选择一个元素

第1种方案:最常规的实现方法

代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import string
import random
x = string.ascii_letters + string.digits + string.punctuation
y = [random.choice(x) for i in range(1000)]
# 生成包含1000个随机字符的列表
z = ''.join(y)
# 把列表中的字符连接成字符串
d = dict()
# 空字典
for ch in z:
d[ch] = d.get(ch,0) + 1
# 修改每个字符的频次
print(d)

运行结果如下所示:

1
2
D:\>python test.py
{'}': 11, 'r': 11, 'Z': 15, 'I': 5, 'a': 19, 'T': 13, '#': 15, 'U': 8, '\\': 11, 'g': 15, '-': 10, 'M': 15, '3': 13, 'd': 12, 'K': 14, 'f': 7, 'v': 9, '>': 6, '2': 9, '=': 12, '<': 10, '6': 15, 'm': 16, 'V': 15, '?': 8, 'F': 13, 'c': 15, '5': 17, ')': 11, '!': 5, 'Y': 8, 'l': 15, 'e': 13, 'P': 6, '&': 9, '[': 15, '@': 13, '+': 6, 't': 13, ']': 14, 'O': 12, 'G': 16, 'k': 11, 'R': 16, 'L': 12, '8': 13, '`': 10, 'W': 11, 'S': 15, 'E': 13, 'N': 11, '~': 11, '9': 7, 'i': 9, ',': 12, '_': 10, '|': 9, 'q': 17, 'J': 12, "'": 12, '{': 10, 'u': 6, '1': 9, '0': 8, '$': 11, 'b': 12, 'A': 11, '(': 12, 'z': 5, 'x': 8, '4': 10, '/': 12, '*': 11, 'o': 11, 'p': 11, 'Q': 7, ':': 7, 's': 12, '.': 7, 'D': 4, '^': 6, '%': 8, 'X': 8, '"': 8, 'y': 9, 'w': 9, 'n': 10, 'H': 11, 'B': 9, ';': 10, 'h': 8, 'j': 8, 'C': 3, '7': 3}

第2种方案:上述代码可以更改为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import string
import random
from collections import defaultdict
x = string.ascii_letters + string.digits + string.punctuation
y = [random.choice(x) for i in range(1000)]
# 生成包含1000个随机字符的列表
z = ''.join(y)
# 把列表中的字符连接成字符串
frequences = defaultdict(int)
print(frequences)
for item in z:
frequences[item] += 1
print(frequences.items())

运行结果如下所示:

1
2
3
D:\>python test.py
defaultdict(<class 'int'>, {})
dict_items([('I', 14), ("'", 9), (':', 13), ('|', 9), ('k', 10), ('[', 9), ('E', 13), ('T', 11), ('K', 12), ('n', 18), ('a', 8), ('-', 13), ('Y', 12), ('{', 16), ('2', 11), ('.', 10), ('z', 9), ('?', 15), ('_', 8), ('A', 13), ('U', 11), ('C', 14), ('O', 14), ('1', 11), ('p', 12), ('`', 7), ('6', 11), ('j', 11), ('<', 8), ('$', 16), ('\\', 7), ('Z', 11), ('3', 10), ('W', 14), ('i', 10), ('x', 8), ('q', 9), ('%', 10), ('B', 7), ('M', 12), ('&', 16), ('N', 13), ('9', 14), ('}', 7), ('Q', 8), ('!', 10), ('/', 10), ('J', 13), ('s', 13), ('G', 8), ('5', 11), ('e', 19), ('L', 6), ('u', 9), ('g', 10), ('7', 16), ('f', 8), ('+', 14), ('0', 12), ('"', 10), ('(', 17), ('b', 6), ('>', 9), ('m', 10), ('v', 11), ('h', 12), ('y', 9), ('l', 10), ('r', 16), (']', 13), ('^', 12), ('~', 8), ('4', 14), ('o', 10), ('w', 10), ('@', 11), ('X', 10), ('S', 6), ('#', 10), ('c', 6), ('R', 14), ('H', 15), (',', 8), ('D', 11), ('=', 8), ('8', 5), (')', 11), ('*', 2), ('d', 7), ('V', 11), (';', 5), ('t', 8), ('P', 8), ('F', 4)])

第3种方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import string
import random
from collections import Counter
x = string.ascii_letters + string.digits + string.punctuation
y = [random.choice(x) for i in range(1000)]
# 生成包含1000个随机字符的列表
z = ''.join(y)
# 把列表中的字符连接成字符串
frequences = Counter(z)
print(frequences.items())
print(frequences.most_common(1))
print(frequences.most_common(3))

运行结果如下所示:

1
2
3
4
D:\>python test.py
dict_items([('!', 4), (':', 6), ('A', 9), ('e', 6), ('R', 5), ('*', 16), ('2', 6), ('m', 17), ('"', 6), ('{', 9), ('i', 13), ('\\', 8), ('r', 8), ('/', 10), ('>', 9), ('f', 14), ('#', 18), ('w', 13), (']', 8), ('J', 9), ('V', 12), ('s', 13), ('}', 11), ('Q', 12), ('5', 13), ('k', 9), ('t', 10), ('S', 9), ('=', 7), ('n', 13), ('7', 13), ('p', 7), ('X', 13), ('~', 5), ('.', 15), ('E', 15), ('&', 12), ('B', 9), ('q', 14), ("'", 8), ('U', 13), ('Z', 7), ('F', 9), (',', 13), ('v', 15), ('a', 8), ('P', 12), ('+', 13), ('G', 14), ('@', 21), ('y', 10), ('$', 9), ('j', 16), ('D', 13), ('b', 9), ('z', 12), ('c', 12), ('3', 12), ('0', 11), (')', 11), ('Y', 15), ('d', 11), ('?', 11), ('I', 5), ('L', 13), ('_', 9), ('O', 9), ('(', 7), ('l', 6), ('^', 8), ('%', 9), ('u', 13), ('<', 13), ('`', 10), ('|', 14), ('C', 16), ('1', 11), ('-', 10), ('o', 8), ('x', 8), ('8', 12), ('M', 12), ('g', 13), ('T', 11), (';', 7), ('H', 12), ('6', 10), ('[', 9), ('K', 11), ('9', 10), ('W', 6), ('4', 11), ('h', 12), ('N', 4)])
[('@', 21)]
[('@', 21), ('#', 18), ('m', 17)]

字典排序sort()

内置函数sorted()可以对字典元素进行排序并返回新列表,充分利用key参数可以实现丰富的排序功能,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> phonebook = {'Linda':'7750','Bob':'9345','Carol':'5834'}
>>> from operator import itemgetter
>>> sorted(phonebook.items(), key=itemgetter(1))
[('Carol', '5834'), ('Linda', '7750'), ('Bob', '9345')]
>>> # 按字典的"值"进行排序
...
>>> sorted(phonebook.items(),key=itemgetter(0))
[('Bob', '9345'), ('Carol', '5834'), ('Linda', '7750')]
>>> #按字典的"键"进行排序
...
>>> sorted(phonebook.items(),key=lambda item:item[0])
[('Bob', '9345'), ('Carol', '5834'), ('Linda', '7750')]
>>> # 按字典的"键"进行排序

提取字典的子集

1
2
3
4
5
6
7
8
>>> students_score = {'jack':80,'james':91, 'leo':100, 'sam':60}
>>> # 提取分数超过90分的学生信息,并变成字典
...
>>> print(students_score)
{'jack': 80, 'james': 91, 'leo': 100, 'sam': 60}
>>> good_score = {name:score for name, score in students_score.items() if score > 90}
>>> print(good_score)
{'james': 91, 'leo': 100}

提取字典中的某个键的值d.get()

如果此键不在字典中,就会返回none。

1
2
3
4
5
>>> d = {'lang':'python'}
>>> print(d)
{'lang': 'python'}
>>> print(d.get("lang"))
python

计算字典的健值

1
2
3
4
5
6
7
>>> stocks = {'wanke':25.6, 'wulingye':32.4, 'maotai':299.4,'huatai':18.6}
>>> print(stocks)
{'wanke': 25.6, 'wulingye': 32.4, 'maotai': 299.4, 'huatai': 18.6}
>>> print(min(stocks.values()))
18.6
>>> print(max(stocks.values()))
299.4

字典的翻转

1
2
3
4
5
6
>>> stocks = {'wanke':25.6, 'wulingye':32.4, 'maotai':299.4,'huatai':18.6}
>>> print(stocks)
{'wanke': 25.6, 'wulingye': 32.4, 'maotai': 299.4, 'huatai': 18.6}
>>> invert_stocks = dict([(v,k) for k,v in stocks.items()])
>>> print(invert_stocks)
{25.6: 'wanke', 32.4: 'wulingye', 299.4: 'maotai', 18.6: 'huatai'}

字典推导式

字典推导和列表推导的使用方法是类似的,只不中括号该改成大括号。直接举例说明:

案例1:大小写key合并

1
2
3
4
5
6
7
8
>>> mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
>>> mcase_frequency = {
... k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0)
... for k in mcase.keys()
... if k.lower() in ['a','b']
... }
>>> print(mcase_frequency)
{'a': 17, 'b': 34}

案例2:快速更换key和value

1
2
3
4
>>> mcase = {'a': 10, 'b': 34}
>>> mcase_frequency = {v: k for k, v in mcase.items()}
>>> print(mcase_frequency)
{10: 'a', 34: 'b'}

使用字典推导式生成符合特定条件的字典

1
2
3
4
5
6
>>> {i:str(i) for i in range(1,5)}
{1: '1', 2: '2', 3: '3', 4: '4'}
>>> x = ['A','B','C','D']
>>> y = ['a','b','b','d']
>>> {i:j for i,j in zip(x,y)}
{'A': 'a', 'B': 'b', 'C': 'b', 'D': 'd'}

再看一个案例,在这个案例中,寻找得到分最高的同学:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
biotest@biotest-VirtualBox:~/python3/03file$ cat dict1.py
#!/usr/bin/python3
scores = {"Zhang San":45, "Li Si":78, "Wang Wu":40, "Zhou Liu":96, "Zhao Qi":65, "Sun Ba":90, "Zheng Jiu":78, "Wu Shi":99,"Dong Shiyi":60}
print(scores)
higest = max(scores.values())
lowest = min(scores.values())
print(higest)
print(lowest)
average = sum(scores.values())/len(scores)
print(average)
higestPerson = [name for name, score in scores.items() if score == higest]
print(higestPerson)
biotest@biotest-VirtualBox:~/python3/03file$ python3 dict1.py
{'Zhang San': 45, 'Li Si': 78, 'Wang Wu': 40, 'Zhou Liu': 96, 'Zhao Qi': 65, 'Sun Ba': 90, 'Zheng Jiu': 78, 'Wu Shi': 99, 'Dong Shiyi': 60}
99
40
72.33333333333333
['Wu Shi']

使用字典推导式提取字典的键与值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
biotest@biotest-VirtualBox:~/python3/03file$ cat test2.py
#!/usr/bin/python3
from random import randint
x = [randint(1,10) for i in range(20)]
# 生成20个范围在1到10之间的随机数
for i in enumerate(x):
print(i)
m = max(x)
print(m)
print([index for index, value in enumerate(x) if value ==m])
print(enumerate(x))
print(x)
biotest@biotest-VirtualBox:~/python3/03file$ python3 test2.py
(0, 10)
(1, 5)
(2, 5)
(3, 2)
(4, 2)
(5, 8)
(6, 4)
(7, 9)
(8, 5)
(9, 2)
(10, 1)
(11, 3)
(12, 9)
(13, 3)
(14, 7)
(15, 6)
(16, 8)
(17, 2)
(18, 10)
(19, 6)
10
[0, 18]
<enumerate object at 0x7f2c5c02ec60>
[10, 5, 5, 2, 2, 8, 4, 9, 5, 2, 1, 3, 9, 3, 7, 6, 8, 2, 10, 6]

注1:其中用到了enumerate(),这是python的内置函数、在字典上是枚举、列举的意思,它可以遍历/可迭代的对象(如列表、字符串),enumerate多用于在for循环中得到计数,利用它可以同时获得索引和值,即需要index和value值的时候可以使用enumerate。

注2:如果不用for循环,enumerate()返回的是一个enumerate对象,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
biotest@biotest-VirtualBox:~/python3/03file$ cat test3.py
#!/usr/bin/python3
from random import randint
x = [randint(1,10) for i in range(20)]
# 生成20个范围在1到10之间的随机数
for i in enumerate(x):
print(i)
print(enumerate(x))
biotest@biotest-VirtualBox:~/python3/03file$ python3 test3.py
(0, 8)
(1, 7)
(2, 2)
(3, 4)
(4, 10)
(5, 4)
(6, 5)
(7, 5)
(8, 6)
(9, 5)
(10, 6)
(11, 3)
(12, 10)
(13, 10)
(14, 7)
(15, 2)
(16, 1)
(17, 7)
(18, 9)
(19, 8)
<enumerate object at 0x7f8b77ae2c60>

查看字典元素的数目len()

使用len()函数,如下所示:

1
2
3
4
5
6
>>> a = {i:str(i) for i in range(1,5)}
>>> a
{1: '1', 2: '2', 3: '3', 4: '4'}
>>> print(len(a))
4
>>>

字典的复制

字典中复制的方法有两种,分别是浅复制(copy)与深复制(deepcopy)。

字典的浅复制copy()

如果直接用=复制字典,其实是为同一个对象贴了两个标签,如下所示:

1
2
3
4
5
6
7
x = {'username':'admin', 'machines':['foo', 'bar', 'bax']}
y = x.copy()
y
x['username'] = 'mlh'
y['machines'].remove('bar')
y
x

运行结果如下所示,可以发现,a与d的id是一样的,它们表示的是同一个对象,如果用copy方法来进行复制,如下所示:

1
2
3
4
5
6
7
8
9
10
>>> x = {'username':'admin', 'machines':['foo', 'bar', 'bax']}
>>> y = x.copy()
>>> y
{'username': 'admin', 'machines': ['foo', 'bar', 'bax']}
>>> x['username'] = 'mlh'
>>> y['machines'].remove('bar')
>>> y
{'username': 'admin', 'machines': ['foo', 'bax']}
>>> x
{'username': 'mlh', 'machines': ['foo', 'bax']}

从运行结果中我们可以看到这些信息:

  1. 我们使用了字典的浅复制方法copy(),生成了一个y变量,开始的时候,yx的内容是一样的;
  2. 接着我们在x中替换掉了username这个键的值,用mlh替换了admin,但y中的username的值并不改变,还是username
  3. 我们在y中删除了machines这个键对应值的bar,同时xmachines这个键对应的值也发生了变化。

这就是浅复制的特点,下面介绍深复制(deepcopy())。

字典的深复制deepcopy()

还是以上面的案例为例说明一下,如下所示:

1
2
3
4
5
6
7
8
from copy import deepcopy
x = {'username':'admin', 'machines':['foo', 'bar', 'bax']}
y = deepcopy(x)
y
x['username'] = 'mlh'
y['machines'].remove('bar')
y
x

运行结果如下所示:

1
2
3
4
5
6
7
8
9
10
11
>>> from copy import deepcopy
>>> x = {'username':'admin', 'machines':['foo', 'bar', 'bax']}
>>> y = deepcopy(x)
>>> y
{'username': 'admin', 'machines': ['foo', 'bar', 'bax']}
>>> x['username'] = 'mlh'
>>> y['machines'].remove('bar')
>>> y
{'username': 'admin', 'machines': ['foo', 'bax']}
>>> x
{'username': 'mlh', 'machines': ['foo', 'bar', 'bax']}

从结果来看,可以得到以下信息 :

  1. xy之间并无影响;
  2. 进行浅复制的时候,语法是y = x.copy(),这是一种方法,而进行深复制的时候,语法是y = deepcopy(x),这是一个函数

参考资料

  1. MagnusLieHetland. Python基础教程.第3版[M]. 人民邮电出版社, 2018.