第 2 章:介绍常用数据类型 序列 字符串 列表 元组 字典 集合
常用数据类型
序列
在介绍 Python 的常用数据类型之前,我们先看看 Python 最基本的数据结构 - 序列(sequence)。
序列的一个特点就是根据索引(index,即元素的位置)来获取序列中的元素,第一个索引是 0,第二个索引是 1,以此类推。
所有序列类型都可以进行某些通用的操作,比如:索引(indexing)
分片(sliceing)
迭代(iteration)
加(adding)
乘(multiplying)
除了上面这些,我们还可以检查某个元素是否属于序列的成员,计算序列的长度等等。
说完序列,我们接下来看看 Python 中常用的数据类型,如下:
其中,列表、元组和字符串都属于序列类型,它们可以进行某些通用的操作,比如索引、分片等;字典属于映射类型,每个元素由键(key)和值(value)构成;集合是一种特殊的类型,它所包含的元素是不重复的。
通用的序列操作
索引
序列中的元素可以通过索引获取,索引从 0 开始。看看下面的例子:
>>> nums = [1, 2, 3, 4, 5] # 列表
>>> nums[0]
1
>>> nums[1]
2
>>> nums[-1] # 索引 -1 表示最后一个元素
5
>>> s = 'abcdef' # 字符串
>>> s[0]
'a'
>>> s[1]
'b'
>>>
>>> a = (1, 2, 3) # 元组
>>> a[0]
1
>>> a[1]
2
注意到,-1 则代表序列的最后一个元素,-2 代表倒数第二个元素,以此类推。
分片
索引用于获取序列中的单个元素,而分片则用于获取序列的部分元素。分片操作需要提供两个索引作为边界,中间用冒号相隔,比如:
>>> numbers = [1, 2, 3, 4, 5, 6]
>>> numbers[0:2] # 列表分片
[1, 2]
>>> numbers[2:5]
[3, 4, 5]
>>> s = 'hello, world' # 字符串分片
>>> s[0:5]
'hello'
>>> a = (2, 4, 6, 8, 10) # 元组分片
>>> a[2:4]
(6, 8)
这里需要特别注意的是,分片有两个索引,第 1 个索引的元素是包含在内的,而第 2 个元素的索引则不包含在内,也就是说,numbers[2:5] 获取的是 numbers[2], numbers[3], numbers[4],没有包括 numbers[5]。
下面列举使用分片的一些技巧。访问最后几个元素
假设需要访问序列的最后 3 个元素,我们当然可以像下面这样做:
>>> numbers = [1, 2, 3, 4, 5, 6]
>>> numbers[3:6]
[4, 5, 6]
有没有更简洁的方法呢?想到可以使用负数形式的索引,你可能会尝试这样做:
>>> numbers = [1, 2, 3, 4, 5, 6]
>>> numbers[-3:-1] # 实际取出的是 numbers[-3], numbers[-2]
[4, 5]
>>> numbers[-3:0] # 左边索引的元素比右边索引出现得晚,返回空序列
[]
上面的两种使用方式并不能正确获取序列的最后 3 个元素,Python 提供了一个捷径:
>>> numbers = [1, 2, 3, 4, 5, 6, 7, 8]
>>> numbers[-3:]
[6, 7, 8]
>>> numbers[5:]
[6, 7, 8]
也就是说,如果希望分片包含最后一个元素,可将第 2 个索引置为空。
如果要复制整个序列,可以将两个索引都置为空:
>>> numbers = [1, 2, 3, 4, 5, 6, 7, 8]
>>> nums = numbers[:]
>>> nums
[1, 2, 3, 4, 5, 6, 7, 8]使用步长
使用分片的时候,步长默认是 1,即逐个访问,我们也可以自定义步长,比如:
>>> numbers = [1, 2, 3, 4, 5, 6, 7, 8]
>>> numbers[0:4]
[1, 2, 3, 4]
>>> numbers[0:4:1] # 步长为 1,不写也可以,默认为 1
[1, 2, 3, 4]
>>> numbers[0:4:2] # 步长为 2,取出 numbers[0], numbers[2]
[1, 3]
>>> numbers[::3] # 等价于 numbers[0:8:3],取出索引为 0, 3, 6 的元素
[1, 4, 7]
另外,步长也可以是负数,表示从右到左取元素:
>>> numbers = [1, 2, 3, 4, 5, 6, 7, 8]
>>> numbers[0:4:-1]
[]
>>> numbers[4:0:-1] # 取出索引为 4, 3, 2, 1 的元素
[5, 4, 3, 2]
>>> numbers[4:0:-2] # 取出索引为 4, 2 的元素
[5, 3]
>>> numbers[::-1] # 从右到左取出所有元素
[8, 7, 6, 5, 4, 3, 2, 1]
>>> numbers[::-2] # 取出索引为 7, 5, 3, 1 的元素
[8, 6, 4, 2]
>>> numbers[6::-2] # 取出索引为 6, 4, 2, 0 的元素
[7, 5, 3, 1]
>>> numbers[:6:-2] # 取出索引为 7 的元素
[8]
这里总结一下使用分片操作的一些方法,分片的使用形式是:
# 左索引:右索引:步长
left_index:right_index:step
要牢牢记住的是:左边索引的元素包括在结果之中,右边索引的元素不包括在结果之中;
当使用一个负数作为步长时,必须让左边索引大于右边索引;
对正数步长,从左向右取元素;对负数步长,从右向左取元素;
加
序列可以进行「加法」操作,如下:
>>> [1, 2, 3] + [4, 5, 6] # 「加法」效果其实就是连接在一起
[1, 2, 3, 4, 5, 6]
>>> (1, 2, 3) + (4, 5, 6)
(1, 2, 3, 4, 5, 6)
>>> 'hello, ' + 'world!'
'hello, world!'
>>> [1, 2, 3] + 'abc'
Traceback (most recent call last):
File "", line 1, in
TypeError: can only concatenate list (not "str") to list
这里需要注意的是:两种相同类型的序列才能「加法」操作。
乘
序列可以进行「乘法」操作,比如:
>>> 'abc' * 3
'abcabcabc'
>>> [0] * 3
[0, 0, 0]
>>> [1, 2, 3] * 3
[1, 2, 3, 1, 2, 3, 1, 2, 3]
in
为了检查一个值是否在序列中,可以使用 in 运算符,比如:
>>> 'he' in 'hello'
True
>>> 'hl' in 'hello'
False
>>> 10 in [6, 8, 10]
True
参考资料《Python 基础教程》
列表
字符串和元组是不可变的,而列表是可变(mutable)的,可以对它进行随意修改。我们还可以将字符串和元组转换成一个列表,只需使用 list 函数,比如:
>>> s = 'hello'
>>> list(s)
['h', 'e', 'l', 'l', 'o']
>>> a = (1, 2, 3)
>>> list(a)
[1, 2, 3]
本文主要介绍常用的列表方法:index
count
append
extend
insert
pop
remove
reverse
sort
index
index 方法用于从列表中找出某个元素的位置,如果有多个相同的元素,则返回第一个元素的位置。
看看例子:
>>> numbers = [1, 2, 3, 4, 5, 5, 7, 8]
>>> numbers.index(5) # 列表有两个 5,返回第一个元素的位置
4
>>> numbers.index(2)
1
>>> words = ['hello', 'world', 'you', 'me', 'he']
>>> words.index('me')
3
>>> words.index('her') # 如果没找到元素,则会抛出异常
Traceback (most recent call last):
File "", line 1, in
ValueError: 'her' is not in list
count
count 方法用于统计某个元素在列表中出现的次数。
看看例子:
>>> numbers = [1, 2, 3, 4, 5, 5, 6, 7]
>>> numbers.count(2) # 出现一次
1
>>> numbers.count(5) # 出现了两次
2
>>> numbers.count(9) # 没有该元素,返回 0
0
append
append 方法用于在列表末尾增加新的元素。
看看例子:
>>> numbers = [1, 2, 3, 4, 5, 5, 6, 7]
>>> numbers.append(8) # 增加 8 这个元素
>>> numbers
[1, 2, 3, 4, 5, 5, 6, 7, 8]
>>> numbers.append([9, 10]) # 增加 [9, 10] 这个元素
>>> numbers
[1, 2, 3, 4, 5, 5, 6, 7, 8, [9, 10]]
extend
extend 方法将一个新列表的元素添加到原列表中。
看看例子:
>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> a.extend(b)
>>> a
[1, 2, 3, 4, 5, 6]
>>>
>>> a.extend(3)
Traceback (most recent call last):
File "", line 1, in
TypeError: 'int' object is not iterable
>>> a.extend([3])
>>> a
[1, 2, 3, 4, 5, 6, 3]
注意到,虽然 append 和 extend 可接收一个列表作为参数,但是 append 方法是将其作为一个元素添加到列表中,而 extend 则是将新列表的元素逐个添加到原列表中。
insert
insert 方法用于将某个元素添加到某个位置。
看看例子:
>>> numbers = [1, 2, 3, 4, 5, 6]
>>> numbers.insert(3, 9)
>>> numbers
[1, 2, 3, 9, 4, 5, 6]
pop
pop 方法用于移除列表中的一个元素(默认是最后一个),并且返回该元素的值。
看看例子:
>>> numbers = [1, 2, 3, 4, 5, 6]
>>> numbers.pop()
6
>>> numbers
[1, 2, 3, 4, 5]
>>> numbers.pop(3)
4
>>> numbers
[1, 2, 3, 5]
remove
remove 方法用于移除列表中的某个匹配元素,如果有多个匹配,则移除第一个。
看看例子:
>>> numbers = [1, 2, 3, 5, 6, 7, 5, 8]
>>> numbers.remove(5) # 有两个 5,移除第 1 个
>>> numbers
[1, 2, 3, 6, 7, 5, 8]
>>> numbers.remove(9) # 没有匹配的元素,抛出异常
Traceback (most recent call last):
File "", line 1, in
ValueError: list.remove(x): x not in list
reverse
reverse 方法用于将列表中的元素进行反转。
看看例子:
>>> numbers = [1, 2, 3, 5, 6, 7, 5, 8]
>>> numbers.reverse()
>>> numbers
[8, 5, 7, 6, 5, 3, 2, 1]
sort
sort 方法用于对列表进行排序,注意该方法会改变原来的列表,而不是返回新的排序列表,另外,sort 方法的返回值是空。
看看例子:
>>> a = [4, 3, 6, 8, 9, 1]
>>> b = a.sort()
>>> b == None # 返回值为空
True
>>> a
[1, 3, 4, 6, 8, 9] # 原列表已经发生改变
如果我们不想改变原列表,而是希望返回一个排序后的列表,可以使用 sorted 函数,如下:
>>> a = [4, 3, 6, 8, 9, 1]
>>> b = sorted(a) # 返回一个排序后的列表
>>> a
[4, 3, 6, 8, 9, 1] # 原列表没有改变
>>> b
[1, 3, 4, 6, 8, 9] # 这是对原列表排序后的列表
注意到,不管是 sort 方法还是 sorted 函数,默认排序都是升序排序。如果你想要降序排序,就需要指定排序参数了。比如,对 sort 方法,可以添加一个 reverse 关键字参数,如下:
>>> a = [4, 3, 6, 8, 9, 1]
>>> a.sort(reverse=True) # 反向排序
>>> a
[9, 8, 6, 4, 3, 1]
该参数对 sorted 函数同样适用:
>>> a = [4, 3, 6, 8, 9, 1]
>>> sorted(a, reverse=True)
[9, 8, 6, 4, 3, 1]
除了 reverse 关键字参数,还可以指定 key 关键字参数,它为每个元素创建一个键,然后所有元素按照这个键来排序,比如我们想根据元素的长度来排序:
>>> s = ['ccc', 'a', 'bb', 'dddd']
>>> s.sort(key=len) # 使用 len 作为键函数,根据元素长度排序
>>> s
['a', 'bb', 'ccc', 'dddd']
另外,我们还可以使用 sorted 进行多列(属性)排序。
看看例子:
>>> students = [
('john', 'B', 15),
('jane', 'A', 12),
('dave', 'B', 10),
('ethan', 'C', 20),
('peter', 'B', 20),
('mike', 'C', 16)
]
>>>
# 对第 3 列排序 (从小到大)
>>> sorted(students, key=lambda student: student[2])
[('dave', 'B', 10),
('jane', 'A', 12),
('john', 'B', 15),
('mike', 'C', 16),
('ethan', 'C', 20),
('peter', 'B', 20)]
# 对第 2 列排序(从小到大),再对第 3 列从大到小排序
>>> sorted(students, key=lambda student: (student[1], -student[2]))
[('jane', 'A', 12),
('peter', 'B', 20),
('john', 'B', 15),
('dave', 'B', 10),
('ethan', 'C', 20),
('mike', 'C', 16)]
如果你想了解更多关于排序的知识,可以参考此文。
小结列表是可变的。
列表常用的方法有 index, count, append, extend 等。
参考资料《Python 基础教程》
元组
在 Python 中,元组是一种不可变序列,它使用圆括号来表示:
>>> a = (1, 2, 3) # a 是一个元组
>>> a
(1, 2, 3)
>>> a[0] = 6 # 元组是不可变的,不能对它进行赋值操作
Traceback (most recent call last):
File "", line 1, in
TypeError: 'tuple' object does not support item assignment
空元组
创建一个空元组可以用没有包含内容的圆括号来表示:
>>> a = ()
>>> a
()
一个值的元组
创建一个值的元组需要在值后面再加一个逗号,这个比较特殊,需要牢牢记住:
>>> a = (12,) # 在值后面再加一个逗号
>>> a
(12,)
>>> type(a)
>>>
>>> b = (12) # 只是使用括号括起来,而没有加逗号,不是元组,本质上是 b = 12
>>> b
12
>>> type(b)
元组操作
元组也是一种序列,因此也可以对它进行索引、分片等。由于它是不可变的,因此就没有类似列表的 append, extend, sort 等方法。
小结元组是不可变的。
创建一个值的元组需要在值后面再加一个逗号。
字符串
字符串也是一种序列,因此,通用的序列操作,比如索引,分片,加法,乘法等对它同样适用。比如:
>>> s = 'hello, '
>>> s[0] # 索引
'h'
>>> s[1:3] # 分片
'el'
>>> s + 'world' # 加法
'hello, world'
>>> s * 2 # 乘法
'hello, hello, '
但需要注意的是,字符串和元组一样,也是不可变的,所以你不能对它进行赋值等操作:
>>> s = 'hello'
>>> s[1] = 'ab' # 不能对它进行赋值
Traceback (most recent call last):
File "", line 1, in
TypeError: 'str' object does not support item assignment
除了通用的序列操作,字符串还有自己的方法,比如 join, lower, upper 等。字符串的方法特别多,这里只介绍一些常用的方法,如下:find
split
join
strip
replace
translate
lower/upper
find
find 方法用于在一个字符串中查找子串,它返回子串所在位置的最左端索引,如果没有找到,则返回 -1。
看看例子:
>>> motto = "to be or not to be, that is a question"
>>> motto.find('be') # 返回 'b' 所在的位置,即 3
3
>>> motto.find('be', 4) # 指定从起始位置开始找,找到的是第 2 个 'be'
16
>>> motto.find('be', 4, 7) # 指定起始位置和终点位置,没有找到,返回 -1
-1
split
split 方法用于将字符串分割成序列。
看看例子:
>>> '/user/bin/ssh'.split('/') # 使用 '/' 作为分隔符
['', 'user', 'bin', 'ssh']
>>> '1+2+3+4+5'.split('+') # 使用 '+' 作为分隔符
['1', '2', '3', '4', '5']
>>> 'that is a question'.split() # 没有提供分割符,默认使用所有空格作为分隔符
['that', 'is', 'a', 'question']
需要注意的是,如果不提供分隔符,则默认会使用所有空格作为分隔符(空格、制表符、换行等)。
join
join 方法可以说是 split 的逆方法,它用于将序列中的元素连接起来。
看看例子:
>>> '/'.join(['', 'user', 'bin', 'ssh'])
'/user/bin/ssh'
>>>
>>> '+'.join(['1', '2', '3', '4', '5'])
'1+2+3+4+5'
>>> ' '.join(['that', 'is', 'a', 'question'])
'that is a question'
>>> ''.join(['h', 'e', 'll', 'o'])
'hello'
>>> '+'.join([1, 2, 3, 4, 5]) # 不能是数字
Traceback (most recent call last):
File "", line 1, in
TypeError: sequence item 0: expected string, int found
strip
strip 方法用于移除字符串左右两侧的空格,但不包括内部,当然也可以指定需要移除的字符串。
看看例子:
>>> ' hello world! '.strip() # 移除左右两侧空格
'hello world!'
>>> '%%% hello world!!! ####'.strip('%#') # 移除左右两侧的 '%' 或 '#'
' hello world!!! '
>>> '%%% hello world!!! ####'.strip('%# ') # 移除左右两侧的 '%' 或 '#' 或空格
'hello world!!!'
replace
replace 方法用于替换字符串中的所有匹配项。
看看例子:
>>> motto = 'To be or not To be, that is a question'
>>> motto.replace('To', 'to') # 用 'to' 替换所有的 'To',返回了一个新的字符串
'to be or not to be, that is a question'
>>> motto # 原字符串保持不变
'To be or not To be, that is a question'
translate
translate 方法和 replace 方法类似,也可以用于替换字符串中的某些部分,但 translate 方法只处理单个字符。
translate 方法的使用形式如下:
str.translate(table[, deletechars]);
其中,table 是一个包含 256 个字符的转换表,可通过 maketrans 方法转换而来,deletechars 是字符串中要过滤的字符集。
看看例子:
>>> from string import maketrans
>>> table = maketrans('aeiou', '12345')
>>> motto = 'to be or not to be, that is a question'
>>> motto.translate(table)
't4 b2 4r n4t t4 b2, th1t 3s 1 q52st34n'
>>> motto
'to be or not to be, that is a question'
>>> motto.translate(table, 'rqu') # 移除所有的 'r', 'q', 'u'
't4 b2 4 n4t t4 b2, th1t 3s 1 2st34n'
可以看到,maketrans 接收两个参数:两个等长的字符串,表示第一个字符串的每个字符用第二个字符串对应位置的字符替代,在上面的例子中,就是 'a' 用 '1' 替代,'e' 用 '2' 替代,等等,注意,是单个字符的代替,而不是整个字符串的替代。因此,motto 中的 o 都被替换为 4,e 都被替换为 2,等等。
lower/upper
lower/upper 用于返回字符串的大写或小写形式。
看看例子:
>>> x = 'PYTHON'
>>> x.lower()
'python'
>>> x
'PYTHON'
>>>
>>> y = 'python'
>>> y.upper()
'PYTHON'
>>> y
'python'
小结字符串是不可变对象,调用对象自身的任意方法,也不会改变该对象自身的内容。相反,这些方法会创建新的对象并返回。
translate 针对单个字符进行替换。
参考资料《python 基础教程》
字典
字典是 Python 中唯一的映射类型,每个元素由键(key)和值(value)构成,键必须是不可变类型,比如数字、字符串和元组。
字典基本操作
这里先介绍字典的几个基本操作,后文再介绍字典的常用方法。创建字典
遍历字典
判断键是否在字典里面
创建字典
字典可以通过下面的方式创建:
>>> d0 = {} # 空字典
>>> d0
{}
>>> d1 = {'name': 'ethan', 'age': 20}
>>> d1
{'age': 20, 'name': 'ethan'}
>>> d1['age'] = 21 # 更新字典
>>> d1
{'age': 21, 'name': 'ethan'}
>>> d2 = dict(name='ethan', age=20) # 使用 dict 函数
>>> d2
{'age': 20, 'name': 'ethan'}
>>> item = [('name', 'ethan'), ('age', 20)]
>>> d3 = dict(item)
>>> d3
{'age': 20, 'name': 'ethan'}
遍历字典
遍历字典有多种方式,这里先介绍一些基本的方式,后文会介绍一些高效的遍历方式。
>>> d = {'name': 'ethan', 'age': 20}
>>> for key in d:
... print '%s: %s' % (key, d[key])
...
age: 20
name: ethan
>>> d['name']
'ethan'
>>> d['age']
20
>>> for key in d:
... if key == 'name':
... del d[key] # 要删除字典的某一项
...
Traceback (most recent call last):
File "", line 1, in
RuntimeError: dictionary changed size during iteration
>>>
>>> for key in d.keys(): # python2 应该使用这种方式, python3 使用 list(d.keys())
... if key == 'name':
... del d[key]
...
>>> d
{'age': 20}
在上面,我们介绍了两种遍历方式:for key in d 和 for key in d.keys(),如果在遍历的时候,要删除键为 key 的某项,使用第一种方式会抛出 RuntimeError,使用第二种方式则不会。
判断键是否在字典里面
有时,我们需要判断某个键是否在字典里面,这时可以用 in 进行判断,如下:
>>> d = {'name': 'ethan', 'age': 20}
>>> 'name' in d
True
>>> d['score'] # 访问不存在的键,会抛出 KeyError
Traceback (most recent call last):
File "", line 1, in
KeyError: 'score'
>>> 'score' in d # 使用 in 判断 key 是否在字典里面
False
字典常用方法
字典有自己的一些操作方法,这里只介绍部分常用的方法:clear
copy
get
setdefault
update
pop
popitem
keys/iterkeys
values/itervalues
items/iteritems
fromkeys
clear
clear 方法用于清空字典中的所有项,这是个原地操作,所以无返回值(或者说是 None)。
看看例子:
>>> d = {'name': 'ethan', 'age': 20}
>>> rv = d.clear()
>>> d
{}
>>> print rv
None
再看看一个例子:
>>> d1 = {}
>>> d2 = d1
>>> d2['name'] = 'ethan'
>>> d1
{'name': 'ethan'}
>>> d2
{'name': 'ethan'}
>>> d1 = {} # d1 变为空字典
>>> d2
{'name': 'ethan'} # d2 不受影响
在上面,d1 和 d2 最初对应同一个字典,而后我们使用 d1 = {} 使其变成一个空字典,但此时 d2 不受影响。如果希望 d1 变成空字典之后,d2 也变成空字典,则可以使用 clear 方法:
>>> d1 = {}
>>> d2 = d1
>>> d2['name'] = 'ethan'
>>> d1
{'name': 'ethan'}
>>> d2
{'name': 'ethan'}
>>> d1.clear() # d1 清空之后,d2 也为空
>>> d1
{}
>>> d2
{}
copy
copy 方法实现的是浅复制(shallow copy)。它具有以下特点:对可变对象的修改保持同步;
对不可变对象的修改保持独立;
看看例子:
# name 的值是不可变对象,books 的值是可变对象
>>> d1 = {'name': 'ethan', 'books': ['book1', 'book2', 'book3']}
>>> d2 = d1.copy()
>>> d2['name'] = 'peter' # d2 对不可变对象的修改不会改变 d1
>>> d2
{'books': ['book1', 'book2', 'book3'], 'name': 'peter'}
>>> d1
{'books': ['book1', 'book2', 'book3'], 'name': 'ethan'}
>>> d2['books'].remove('book2') # d2 对可变对象的修改会影响 d1
>>> d2
{'books': ['book1', 'book3'], 'name': 'peter'}
>>> d1
{'books': ['book1', 'book3'], 'name': 'ethan'}
>>> d1['books'].remove('book3') # d1 对可变对象的修改会影响 d2
>>> d1
{'books': ['book1'], 'name': 'ethan'}
>>> d2
{'books': ['book1'], 'name': 'peter'}
和浅复制对应的是深复制(deep copy),它会创造出一个副本,跟原来的对象没有关系,可以通过 copy 模块的 deepcopy 函数来实现:
>>> from copy import deepcopy
>>> d1 = {'name': 'ethan', 'books': ['book1', 'book2', 'book3']}
>>> d2 = deepcopy(d1) # 创造出一个副本
>>>
>>> d2['books'].remove('book2') # 对 d2 的任何修改不会影响到 d1
>>> d2
{'books': ['book1', 'book3'], 'name': 'ethan'}
>>> d1
{'books': ['book1', 'book2', 'book3'], 'name': 'ethan'}
>>>
>>> d1['books'].remove('book3') # 对 d1 的任何修改也不会影响到 d2
>>> d1
{'books': ['book1', 'book2'], 'name': 'ethan'}
>>> d2
{'books': ['book1', 'book3'], 'name': 'ethan'}
get
当我们试图访问字典中不存在的项时会出现 KeyError,但使用 get 就可以避免这个问题。
看看例子:
>>> d = {}
>>> d['name']
Traceback (most recent call last):
File "", line 1, in
KeyError: 'name'
>>> print d.get('name')
None
>>> d.get('name', 'ethan') # 'name' 不存在,使用默认值 'ethan'
'ethan'
>>> d
{}
setdefault
setdefault 方法用于对字典设定键值。使用形式如下:
dict.setdefault(key, default=None)
看看例子:
>>> d = {}
>>> d.setdefault('name', 'ethan') # 返回设定的默认值 'ethan'
'ethan'
>>> d # d 被更新
{'name': 'ethan'}
>>> d['age'] = 20
>>> d
{'age': 20, 'name': 'ethan'}
>>> d.setdefault('age', 18) # age 已存在,返回已有的值,不会更新字典
20
>>> d
{'age': 20, 'name': 'ethan'}
可以看到,当键不存在的时候,setdefault 返回设定的默认值并且更新字典。当键存在的时候,会返回已有的值,但不会更新字典。
update
update 方法用于将一个字典添加到原字典,如果存在相同的键则会进行覆盖。
看看例子:
>>> d = {}
>>> d1 = {'name': 'ethan'}
>>> d.update(d1) # 将字典 d1 添加到 d
>>> d
{'name': 'ethan'}
>>> d2 = {'age': 20}
>>> d.update(d2) # 将字典 d2 添加到 d
>>> d
{'age': 20, 'name': 'ethan'}
>>> d3 = {'name': 'michael'} # 将字典 d3 添加到 d,存在相同的 key,则覆盖
>>> d.update(d3)
>>> d
{'age': 20, 'name': 'michael'}
items/iteritems
items 方法将所有的字典项以列表形式返回,这些列表项的每一项都来自于(键,值)。我们也经常使用这个方法来对字典进行遍历。
看看例子:
>>> d = {'name': 'ethan', 'age': 20}
>>> d.items()
[('age', 20), ('name', 'ethan')]
>>> for k, v in d.items():
... print '%s: %s' % (k, v)
...
age: 20
name: ethan
iteritems 的作用大致相同,但会返回一个迭代器对象而不是列表,同样,我们也可以使用这个方法来对字典进行遍历,而且这也是推荐的做法:
>>> d = {'name': 'ethan', 'age': 20}
>>> d.iteritems()
>>> for k, v in d.iteritems():
... print '%s: %s' % (k, v)
...
age: 20
name: ethan
keys/iterkeys
keys 方法将字典的键以列表形式返回,iterkeys 则返回针对键的迭代器。
看看例子:
>>> d = {'name': 'ethan', 'age': 20}
>>> d.keys()
['age', 'name']
>>> d.iterkeys()
values/itervalues
values 方法将字典的值以列表形式返回,itervalues 则返回针对值的迭代器。
看看例子:
>>> d = {'name': 'ethan', 'age': 20}
>>> d.values()
[20, 'ethan']
>>> d.itervalues()
pop
pop 方法用于将某个键值对从字典移除,并返回给定键的值。
看看例子:
>>> d = {'name': 'ethan', 'age': 20}
>>> d.pop('name')
'ethan'
>>> d
{'age': 20}
popitem
popitem 用于随机移除字典中的某个键值对。
看看例子:
>>> d = {'id': 10, 'name': 'ethan', 'age': 20}
>>> d.popitem()
('age', 20)
>>> d
{'id': 10, 'name': 'ethan'}
>>> d.popitem()
('id', 10)
>>> d
{'name': 'ethan'}
对元素为字典的列表排序
事实上,我们很少直接对字典进行排序,而是对元素为字典的列表进行排序。
比如,存在下面的 students 列表,它的元素是字典:
students = [
{'name': 'john', 'score': 'B', 'age': 15},
{'name': 'jane', 'score': 'A', 'age': 12},
{'name': 'dave', 'score': 'B', 'age': 10},
{'name': 'ethan', 'score': 'C', 'age': 20},
{'name': 'peter', 'score': 'B', 'age': 20},
{'name': 'mike', 'score': 'C', 'age': 16}
]按 score 从小到大排序
>>> sorted(students, key=lambda stu: stu['score'])
[{'age': 12, 'name': 'jane', 'score': 'A'},
{'age': 15, 'name': 'john', 'score': 'B'},
{'age': 10, 'name': 'dave', 'score': 'B'},
{'age': 20, 'name': 'peter', 'score': 'B'},
{'age': 20, 'name': 'ethan', 'score': 'C'},
{'age': 16, 'name': 'mike', 'score': 'C'}]
需要注意的是,这里是按照字母的 ascii 大小排序的,所以 score 从小到大,即从 'A' 到 'C'。按 score 从大到小排序
>>> sorted(students, key=lambda stu: stu['score'], reverse=True) # reverse 参数
[{'age': 20, 'name': 'ethan', 'score': 'C'},
{'age': 16, 'name': 'mike', 'score': 'C'},
{'age': 15, 'name': 'john', 'score': 'B'},
{'age': 10, 'name': 'dave', 'score': 'B'},
{'age': 20, 'name': 'peter', 'score': 'B'},
{'age': 12, 'name': 'jane', 'score': 'A'}]按 score 从小到大,再按 age 从小到大
>>> sorted(students, key=lambda stu: (stu['score'], stu['age']))
[{'age': 12, 'name': 'jane', 'score': 'A'},
{'age': 10, 'name': 'dave', 'score': 'B'},
{'age': 15, 'name': 'john', 'score': 'B'},
{'age': 20, 'name': 'peter', 'score': 'B'},
{'age': 16, 'name': 'mike', 'score': 'C'},
{'age': 20, 'name': 'ethan', 'score': 'C'}]按 score 从小到大,再按 age 从大到小
>>> sorted(students, key=lambda stu: (stu['score'], -stu['age']))
[{'age': 12, 'name': 'jane', 'score': 'A'},
{'age': 20, 'name': 'peter', 'score': 'B'},
{'age': 15, 'name': 'john', 'score': 'B'},
{'age': 10, 'name': 'dave', 'score': 'B'},
{'age': 20, 'name': 'ethan', 'score': 'C'},
{'age': 16, 'name': 'mike', 'score': 'C'}]
参考资料
集合
集合(set)和字典(dict)类似,它是一组 key 的集合,但不存储 value。集合的特性就是:key 不能重复。
集合常用操作
创建集合
set 的创建可以使用 {} 也可以使用 set 函数:
>>> s1 = {'a', 'b', 'c', 'a', 'd', 'b'} # 使用 {}
>>> s1
set(['a', 'c', 'b', 'd'])
>>>
>>> s2 = set('helloworld') # 使用 set(),接收一个字符串
>>> s2
set(['e', 'd', 'h', 'l', 'o', 'r', 'w'])
>>>
>>> s3 = set(['.mp3', '.mp4', '.rmvb', '.mkv', '.mp3']) # 使用 set(),接收一个列表
>>> s3
set(['.mp3', '.mkv', '.rmvb', '.mp4'])
遍历集合
>>> s = {'a', 'b', 'c', 'a', 'd', 'b'}
>>> for e in s:
... print e
...
a
c
b
d
添加元素
add() 方法可以将元素添加到 set 中,可以重复添加,但没有效果。
>>> s = {'a', 'b', 'c', 'a', 'd', 'b'}
>>> s
set(['a', 'c', 'b', 'd'])
>>> s.add('e')
>>> s
set(['a', 'c', 'b', 'e', 'd'])
>>> s.add('a')
>>> s
set(['a', 'c', 'b', 'e', 'd'])
>>> s.add(4)
>>> s
set(['a', 'c', 'b', 4, 'd', 'e'])
删除元素
remove() 方法可以删除集合中的元素, 但是删除不存在的元素,会抛出 KeyError,可改用 discard()。
看看例子:
>>> s = {'a', 'b', 'c', 'a', 'd', 'b'}
>>> s
set(['a', 'c', 'b', 'd'])
>>> s.remove('a') # 删除元素 'a'
>>> s
set(['c', 'b', 'd'])
>>> s.remove('e') # 删除不存在的元素,会抛出 KeyError
Traceback (most recent call last):
File "", line 1, in
KeyError: 'e'
>>> s.discard('e') # 删除不存在的元素, 不会抛出 KeyError
交集/并集/差集
Python 中的集合也可以看成是数学意义上的无序和无重复元素的集合,因此,我们可以对两个集合作交集、并集等。
看看例子:
>>> s1 = {1, 2, 3, 4, 5, 6}
>>> s2 = {3, 6, 9, 10, 12}
>>> s3 = {2, 3, 4}
>>> s1 & s2 # 交集
set([3, 6])
>>> s1 | s2 # 并集
set([1, 2, 3, 4, 5, 6, 9, 10, 12])
>>> s1 - s2 # 差集
set([1, 2, 4, 5])
>>> s3.issubset(s1) # s3 是否是 s1 的子集
True
>>> s3.issubset(s2) # s3 是否是 s2 的子集
False
>>> s1.issuperset(s3) # s1 是否是 s3 的超集
True
>>> s1.issuperset(s2) # s1 是否是 s2 的超集
False
参考资料