python 字典有序还是无序
在 Python 中,字典(dictionary)是一种非常常用的数据结构,用于存储键-值(key-value)对。Python 字典与列表、元组等数据类型不同的是,它是无序的。
Python 字典的定义
Python 字典的定义非常简单,用一对大括号 {} 括起来,里面用逗号分隔开键值对即可,如下所示:
dict_1 = {'a': 1, 'b': 2, 'c': 3}
这里定义了一个名为 dict_1
的字典,其中包含三个键值对:’a’: 1, ‘b’: 2, ‘c’: 3。其中,’a’, ‘b’, ‘c’ 是字典的键(key),它们对应的值(value)分别为 1,2,3。
和列表、元组一样,可以通过索引来访问字典中的元素。不过,在字典中,索引要使用键来完成。例如,要访问字典 dict_1
中的键 'a'
,可以使用如下代码:
value = dict_1['a']
这里 dict_1['a']
表示字典 dict_1
中键为 'a'
对应的值。执行后,变量 value
的值为 1
。
Python 字典的无序性质
虽然在字典定义时指定键值对是按照先后顺序排列的,但是,在 Python 3.6 之前,字典并没有保证按照插入顺序对键值对进行存储。这意味着,在 Python 3.6 之前版本中,字典的遍历顺序并不一定是通过键值对添加顺序实现的。
例如,在 Python 3.5 及之前的版本中,以下的代码:
dict_1 = {'b': 2, 'a': 1, 'c': 3}
print(dict_1)
可能输出以下内容(不一定是这个顺序):
{'a': 1, 'b': 2, 'c': 3}
从 Python 3.6 开始,Python 字典提供了有序字典(OrderedDict)这种数据类型,可以保证键值对存储的顺序与插入顺序一致。如果需要创建有序字典,可以使用如下代码:
from collections import OrderedDict
dict_2 = OrderedDict({'b': 2, 'a': 1, 'c': 3})
print(dict_2)
输出:
OrderedDict([('b', 2), ('a', 1), ('c', 3)])
需要注意的是,虽然有序字典保证了键值对存储的顺序,但是在其他方面,它和普通字典并没有什么区别。
Python 字典的遍历
在 Python 中,可以使用 for
循环来遍历一个字典,如下所示:
dict_1 = {'a': 1, 'b': 2, 'c': 3}
for key in dict_1:
print(key, dict_1[key])
输出:
a 1
b 2
c 3
需要注意的是,字典的遍历顺序不一定是按照插入顺序进行的。如果要遍历一个有序字典,可以使用 OrderedDict 类型。
此外,还可以使用 items()
方法来遍历一个字典,这个方法返回一个包含字典所有键值对的列表。例如,以下代码可以遍历字典 dict_1
:
dict_1 = {'a': 1, 'b': 2, 'c': 3}
for key, value in dict_1.items():
print(key, value)
输出:
a 1
b 2
c 3
需要注意的是,虽然 items()
方法返回的列表中的键值对顺序与字典定义时的顺序相同,但是这并不意味着字典本身是有序的。只有在使用有序字典(OrderedDict)时才有这种保证。
除了 items()
方法之外,还可以使用 keys()
方法和 values()
方法来分别获取字典的键和值,这两个方法返回的分别是一个键和值的列表。例如,以下代码可以获取字典 dict_1
的所有键:
dict_1 = {'a': 1, 'b': 2, 'c': 3}
keys = dict_1.keys()
print(keys)
输出:
dict_keys(['a', 'b', 'c'])
需要注意的是,keys()
方法返回的列表并不保证顺序与字典定义时的顺序一致。如果需要保证顺序一致,可以使用有序字典。
Python 3.7 对字典的改进
在 Python 3.7 中,字典的实现方式发生了改变,对于小型的字典,Python 使用的是一个基于二元组 (key, value) 的线性探测散列表实现,这是之前版本的默认实现。而对于大型的字典,Python 3.7 引入了一种新的实现方式,它使用了基于论文 “Compact Hash Tables: A Practical Collision Resolution Technique for Interactive Systems” 中提出的 Robin Hood hashing 算法。
Robin Hood hashing 算法是一种探测式散列算法,用于解决哈希冲突。这种算法的核心思想是,将大的键值对向散列表中心移动,小的键值对向散列表边缘移动,以最大化可用空间。
这种新的实现方式在插入、删除等操作时,都要比之前的实现方式更高效。在 Python 3.7 中,字典的实现方式也是默认使用这种方法。
Python 字典的应用
Python 字典的应用十分广泛,几乎在所有的 Python 编程中都能见到。下面列举几个常见的应用场景。
统计单词频率
可以使用 Python 字典来统计一段文本中单词的频率。具体来说,可以将文本分割为单个单词,然后用一个字典来保存每个单词出现的次数。
以下是一个例子,统计一段话中每个单词出现的次数:
text = "I am a boy. You are a girl. He is a dog. She is a cat."
words = text.split()
freq = {}
for word in words:
if word in freq:
freq[word] += 1
else:
freq[word] = 1
print(freq)
输出:
{'I': 1, 'am': 1, 'a': 4, 'boy.': 1, 'You': 1, 'are': 1, 'girl.': 1, 'He': 1, 'is': 2, 'dog.': 1, 'She': 1, 'cat.': 1}
可以看到,字典 freq
中保存了每个单词出现的次数。
构建树形结构
可以使用 Python 字典来构建树形结构。具体来说,在构建树形结构时,可以使用一个字典来描述每个节点,其中键表示节点的名称,值表示节点的子节点。
以下是一个例子,构建一个树形结构:
tree = {'A': {'B': {'C': {},
'D': {}},
'E': {'F': {},
'G': {'H': {}}}}}
print(tree)
输出:
{'{'A': {'B': {'C': {}, 'D': {}}, 'E': {'F': {}, 'G': {'H': {}}}}}
可以看到,这个字典描述了一个树形结构,根节点的名称为 'A'
,有两个子节点 'B'
和 'E'
。其中节点 'B'
有两个子节点 'C'
和 'D'
,节点 'E'
有两个子节点 'F'
和 'G'
,节点 'G'
又有一个子节点 'H'
。
编写某些 Web 框架
某些 Web 框架(如 Flask)使用 Python 字典来存储关于路由和视图函数的信息。具体来说,可以将路由映射表存储为字典类型,其中键为路由路径,值为对应的视图函数。
以下是一个例子,定义一个 Flask 路由映射表:
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello, World!'
@app.route('/about')
def about():
return 'About us'
@app.route('/contact')
def contact():
return 'Contact us'
if __name__ == '__main__':
app.run()
可以看到,在这个例子中,路由映射表就是通过使用 Python 字典来实现的。
结论
虽然 Python 字典是无序的,但是它们在 Python 编程中的应用十分广泛。需要注意的是,在 Python 3.6 之前,字典并没有保证按照插入顺序对键值对进行存储。如果需要有序的字典,可以使用 OrderedDict
类型。另外,在 Python 3.7 中,字典实现方式的改进也使其在性能方面更加优秀。对于 Python 开发者来说,熟悉并灵活运用 Python 字典,可以帮助他们更好地完成自己的工作。