相比于列表和元组,字典的性能更优,特别是对于查找、添加和删除操作,字典都能在常数时间复杂度内完成。
而集合和字典基本相同,唯一的区别,就是集合没有键和值的配对,是一系列无序的、唯一的元素组合。
1.字典和集合的创建
>>>d1 = {'name': 'jason', 'age': 20, 'gender': 'male'}
>>>d2 = dict({'name': 'jason', 'age': 20, 'gender': 'male'})
>>>d3 = dict([('name', 'jason'), ('age', 20), ('gender', 'male')])
>>>d4 = dict(name='jason', age=20, gender='male')
>>>d1 == d2 == d3 == d4
True
>>>s1 = {1, 2, 3}
>>>s2 = set([1, 2, 3])
>>>s1 == s2
True
2.字典和集合的特性
1)Python 中字典和集合
-
key的类型必须为不可变类型:字符串、数字、元组。
-
value的类型为任意类型。
2)字典的元素访问
字典访问可以直接索引键,如果不存在,就会抛出异常:
>>>d ={'name': 'jason', 'age': 20}
>>>d['name']
'jason'
>>>d['location']
Traceback (most recent call last): File"<stdin>", line 1, in<module>KeyError: 'location'
也可以使用 get(key, default) 函数来进行索引。如果键不存在,调用 get() 函数可以返回一个默认值。比如下面这个示例,返回了'null'
>>>d ={'name': 'jason', 'age': 20}
>>>d.get('name')
'jason'
>>>d.get('location', 'null')#可以自行设置默认值'null'
3) 集合的访问
集合并不支持索引操作,因为集合本质上是一个哈希表,和列表不一样。所以,下面这样的操作是错误的,Python 会抛出异常:
>>>s ={1, 2, 3}
>>>s[0]
Traceback (most recent call last): File"<stdin>", line 1, in<module>TypeError: 'set'objectdoes notsupport indexing
4)判断一个元素在不在字典或集合内,我们可以用 value in dict/set 来判断
>>>s ={1, 2, 3}
>>>1 in s
True
>>>10 in s
False
>>>d ={'name': 'jason', 'age': 20}
>>>'name' in d
True
>>>'location' in d
False
5) 字典和集合也同样支持增加、删除、更新等操作
集合的 pop() 操作是删除集合中最后一个元素,可是集合本身是无序的,无法知道会删除哪个元素,因此这个操作得谨慎使用!❗️❗️
6) 对字典或集合进行排序
对字典的排序:
>>>d ={'b': 1, 'a': 2, 'c': 10}
>>>d_sorted_by_key =sorted(d.items(), key=lambdax: x[0]) # 根据字典键的升序排序
>>>d_sorted_by_value =sorted(d.items(), key=lambdax: x[1]) # 根据字典值的升序排序
>>>d_sorted_by_key
[('a', 2), ('b', 1), ('c',10)]
>>>d_sorted_by_value
[('b', 1), ('a', 2), ('c', 10)]
对集合排序
#直接调用 sorted(set) 即可,结果会返回一个排好序的列表
>>>s ={3, 4, 2, 1}
>>>sorted(s) # 对集合的元素进行升序排序
[1, 2, 3, 4]
7) 字典和集合性能
字典和集合是进行过性能高度优化的数据结构,特别是对于查找、添加和删除操作
8)集合运算
集合是由不重复元素组成的无序容器。基本用法包括成员检测、消除重复元素。集合对象支持合集、交集、差集、对称差分等数学运算。
创建集合用花括号或 set()
函数。注意,创建空集合只能用 set()
,不能用 {}
,{}
创建的是空字典,下一小节介绍数据结构:字典。
以下是一些简单的示例
>>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
>>> print(basket) # show that duplicates have been removed
{'orange', 'banana', 'pear', 'apple'}
>>> 'orange' in basket # fast membership testing
True
>>> 'crabgrass' in basket
False
>>> # Demonstrate set operations on unique letters from two words
...
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a # unique letters in a
{'a', 'r', 'b', 'c', 'd'}
>>> a - b # letters in a but not in b
{'r', 'd', 'b'}
>>> a | b # letters in a or b or both
{'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
>>> a & b # letters in both a and b
{'a', 'c'}
>>> a ^ b # letters in a or b but not both
{'r', 'd', 'b', 'm', 'z', 'l'}
与 列表推导式 类似,集合也支持推导式:
>>> a = {x for x in 'abracadabra' if x not in 'abc'}
>>> a
{'r', 'd'}
字典推导式可以用任意键值表达式创建字典:
>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}
关键字是比较简单的字符串时,直接用关键字参数指定键值对更便捷:
>>> dict(sape=4139, guido=4127, jack=4098)
{'sape': 4139, 'guido': 4127, 'jack': 4098}
9) 循环的技巧
在字典中循环时,用 items()
方法可同时取出键和对应的值:
>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
>>> for k, v in knights.items():
... print(k, v)
...
gallahad the pure
robin the brave
在序列中循环时,用 enumerate()
函数可以同时取出位置索引和对应的值:
>>> for i, v in enumerate(['tic', 'tac', 'toe']):
... print(i, v)
...
0 tic
1 tac
2 toe
同时循环两个或多个序列时,用 zip()
函数可以将其内的元素一一匹配:
>>> questions = ['name', 'quest', 'favorite color']
>>> answers = ['lancelot', 'the holy grail', 'blue']
>>> for q, a in zip(questions, answers):
... print('What is your {0}? It is {1}.'.format(q, a))
...
What is your name? It is lancelot.
What is your quest? It is the holy grail.
What is your favorite color? It is blue.
逆向循环序列时,先正向定位序列,然后调用 reversed()
函数:
>>> for i in reversed(range(1, 10, 2)):
... print(i)
...
9
7
5
3
1
按指定顺序循环序列,可以用 sorted()
函数,在不改动原序列的基础上,返回一个重新的序列:
>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> for i in sorted(basket):
... print(i)
...
apple
apple
banana
orange
orange
pear
使用 set()
去除序列中的重复元素。使用 sorted()
加 set()
则按排序后的顺序,循环遍历序列中的唯一元素:
>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> for f in sorted(set(basket)):
... print(f)
...
apple
banana
orange
pear
一般来说,在循环中修改列表的内容时,创建新列表比较简单,且安全:
>>> import math
>>> raw_data = [56.2, float('NaN'), 51.7, 55.3, 52.5, float('NaN'), 47.8]
>>> filtered_data = []
>>> for value in raw_data:
... if not math.isnan(value):
... filtered_data.append(value)
...
>>> filtered_data
[56.2, 51.7, 55.3, 52.5, 47.8]
10) 深入条件控制
while
和 if
条件句不只可以进行比较,还可以使用任意运算符。
比较运算符 in
和 not in
校验序列里是否存在某个值。运算符 is
和 is not
比较两个对象是否为同一个对象。所有比较运算符的优先级都一样,且低于数值运算符。
比较操作支持链式操作。例如,a < b == c
校验 a
是否小于 b
,且 b
是否等于 c
。
比较操作可以用布尔运算符 and
和 or
组合,并且,比较操作(或其他布尔运算)的结果都可以用 not
取反。这些操作符的优先级低于比较操作符;not
的优先级最高, or
的优先级最低,因此,A and not B or C
等价于 (A and (not B)) or C
。与其他运算符操作一样,此处也可以用圆括号表示想要的组合。
布尔运算符 and
和 or
也称为 短路 运算符:其参数从左至右解析,一旦可以确定结果,解析就会停止。例如,如果 A
和 C
为真,B
为假,那么 A and B and C
不会解析 C
。用作普通值而不是布尔值时,短路操作符返回的值通常是最后一个变量。
还可以把比较操作或逻辑表达式的结果赋值给变量,例如:
>>> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance'
>>> non_null = string1 or string2 or string3
>>> non_null
'Trondheim'
注意,Python 与 C 不同,在表达式内部赋值必须显式使用 海象运算符 :=
。 这避免了 C 程序中常见的问题:要在表达式中写 ==
时,却写成了 =
。
11) 比较大小
序列对象可以与相同序列类型的其他对象比较。这种比较使用 字典式 顺序:首先,比较前两个对应元素,如果不相等,则可确定比较结果;如果相等,则比较之后的两个元素,以此类推,直到其中一个序列结束。如果要比较的两个元素本身是相同类型的序列,则递归地执行字典式顺序比较。如果两个序列中所有的对应元素都相等,则两个序列相等。如果一个序列是另一个的初始子序列,则较短的序列可被视为较小(较少)的序列。 对于字符串来说,字典式顺序使用 Unicode 码位序号排序单个字符。下面列出了一些比较相同类型序列的例子:
(1, 2, 3) < (1, 2, 4)
[1, 2, 3] < [1, 2, 4]
'ABC' < 'C' < 'Pascal' < 'Python'
(1, 2, 3, 4) < (1, 2, 4)
(1, 2) < (1, 2, -1)
(1, 2, 3) == (1.0, 2.0, 3.0)
(1, 2, ('aa', 'ab')) < (1, 2, ('abc', 'a'), 4)
注意,对不同类型的对象来说,只要待比较的对象提供了合适的比较方法,就可以使用 <
和 >
进行比较。例如,混合数值类型通过数值进行比较,所以,0 等于 0.0,等等。否则,解释器不会随便给出一个对比结果,而是触发 TypeError
异常。