geekdoc-python-zh/docs/pythonland/32.md

14 KiB
Raw Permalink Blame History

Python 字典:如何创建和使用,附示例

原文:https://python.land/python-data-types/dictionaries

Python 字典是该语言最强大的数据类型之一。在其他编程语言和一般的计算机科学中,字典也被称为关联数组。它们允许您将一个或多个键与值相关联。如果你熟悉 JSON ,你可能会有宾至如归的感觉。字典的语法非常类似于 JSON 文档的语法。

目录

创建 Python 字典

让我们看看如何在 Python REPL 中创建和使用 Python 字典:

>>> phone_numbers = { 'Jack': '070-02222748',
                      'Pete': '010-2488634' }
>>> my_empty_dict = { }
>>> phone_numbers['Jack']
'070-02222748'

字典是用花括号创建的。在这些大括号内,我们可以添加一个或多个键值对。当添加多个键值对时,这些键值对用逗号分隔。我们示例中的第一个字典将键(如 Jack 和 Pete)与值(他们的电话号码)相关联。第二本字典是一本空的。

访问和删除键值对

既然您已经看到了如何初始化一个字典,那么让我们来看看如何在一个已经存在的字典中添加和删除条目:

>>> phone_numbers['Eric'] = '06-10101010'
>>> del(phone_numbers['Jack'])
>>> phone_numbers
{'Pete': '010-2488634', 'Eric': '06-10101010'}

默认值和 dict.get()

从字典中检索单个值的另一种方法是使用 get-方法。优势?如果找不到该键,它将返回默认值None。您也可以指定自己的默认值。

使用 get-method您不必用 try 包围操作…除了。当处理从 YAML 或 JSON 文件解析的配置数据时,它是理想的,在这些文件中,您的软件为未设置的配置项提供默认值。

一个例子:

>>> config = { 'host': 'example.org' }
>>> config.get('port', 80)
80
>>> config.get('schema')
>>> 

最后一个 get 调用返回None,但是最新版本的 REPL 不打印任何内容。

覆盖字典条目

要覆盖一个条目,只需给它分配一个新值。你不需要先做这件事。例如:

>>> phone_numbers = { 'Jack': '070-02222748',
                      'Pete': '010-2488634' }
>>> phone_numbers['Jack'] = '1234567'

使用 try…除了

如果请求的键不存在,抛出类型为KeyError异常:

>>> phone_numbers['lisa']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'lisa'

如果您知道数据可能会丢失,例如,当解析来自外界的输入时,请确保用try ... except KeyError 包围您的代码。我已经在我的关于 try 的文章的最佳实践部分详细解释了这一点……除了。在那篇文章中,我还解释了请求原谅,而不是许可的概念。例如,在尝试访问某个键之前不检查它是否存在。相反,只要试一试,如果异常不存在就捕捉它。

有效的字典值

你可以把任何东西放进字典里。你不局限于数字字符串。事实上,您可以将字典和 Python 列表放入字典中,并以非常自然的方式访问嵌套的值:

>>> a = { 'sub_dict': { 'b': True },
          'mylist': [100, 200, 300] }
>>> a['sub_dict']['b']
True
>>> a['mylist'][0]
100

Python 的 JSON 解码和编码库在解析更复杂的 JSON 文档时使用了 Python 的这个特性。它创建列表、字典和其他有效数据类型的嵌套树。

有效的字典键

如果你愿意,你也可以疯狂地使用你的字典键。唯一的要求是密钥是可散列的。像列表、字典和集合这样的可变类型不起作用,并导致类似于TypeError: unhashable type: dict的错误。

除了这个限制之外,您可以使用所有数据类型作为字典键,包括本地类型,如元组float[int](https://python.land/python-data-types/python-integer),甚至是类名或基于类的对象。尽管对大多数人来说完全没用,我还是要演示一下:

>>> crazy_dictionary = { int: 1, float: 2, dict: 3 }
>>> crazy_dictionary[dict]
3
>>> class P:
...     pass
... 
>>> crazy_dictionary[P]=1
>>> p = P()
>>> crazy_dictionary[p]=2

一个更可能的用例是使用数字作为键。例如,考虑马拉松赛跑者的注册:

>>> runners = { 1000: 'Jack', 1001: 'Eric', 
                1002: 'Lisa' }
>>> runners[1001]
'Eric'

创建 Python 字典的更多方法

根据您的数据源,有更高级的方法来初始化字典,这可能会派上用场。

使用 dict()构造函数

dict()函数从键值对(元组)的序列或列表构建一个字典:

>>> dict([ ('Jack', '070-02222748'), 
           ('Pete', '010-2488634'), 
           ('Eric', '06-10101010') ])
{'Jack': '070-02222748', 'Pete': '010-2488634', 'Eric': '06-10101010'}

词典释义

类似于 list comprehensions ,你也可以使用字典 comprehensions 来创建一个新的字典。列表只包含值,而字典包含键/值对。因此,字典理解需要定义这两者。除此之外,语法是相似的:

>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}

请阅读我关于列表理解的文章,以获得关于理解的更详细的解释。

使用 dict.fromkeys

dict.fromkeys(keys, value)方法根据提供给它的keys列表创建一个新字典。所有元素的值将被设置为所提供的value,或者默认为None,如果您不提供值的话。

Thank you for reading my tutorials. I write these in my free time, and it requires a lot of time and effort. I use ads to keep writing these free articles, I hope you understand! Support me by disabling your adblocker on my website or, alternatively, buy me some coffee. It's much appreciated and allows me to keep working on this site!

请参见以下代码:

>>> names = ('Eric', 'Martha', 'Ellen')
>>> phone_numbers = dict.fromkeys(names, None)
>>> phone_numbers
{'Ellen': None, 'Eric': None, 'Martha': None}

将 JSON 对象解析为字典

正如在使用 JSON 一节中所解释的,您也可以像这样将 JSON 数据解码成字典:

>>> import json
>>> jsonstring = '{ "name": "erik", "age": 38, 
                    "married": true}'
>>> json.loads(jsonstring)
{'name': 'erik', 'age': 38, 'married': True}

检查一个关键字是否存在于 Python 字典中

您可以使用关键字innot in检查字典中是否存在关键字:

>>> 'Jack' in phone_numbers
True
>>> 'Jack' not in phone_numbers
False

获取 Python 字典的长度

内置 Python len()函数返回字典中键/值对的数量:

>>> phone_numbers = { 'Jack': '070-02222748', 
                      'Pete': '010-2488634', 
                      'Eric': '06-10101010' }
>>> len(phone_numbers)
3

字典查看对象

一些内置的字典方法返回一个视图对象,提供一个关于字典的键和值的窗口。在我们开始使用这样的视图对象之前,您需要理解一个重要的概念:视图对象中的值随着字典内容的变化而变化。

关键字()和值()

这个例子很好地说明了这一点,在这个例子中,我们使用了其中的两个视图:键()和值()。Keys 返回字典中所有键的视图,而 values()返回其所有值的视图:

https://crumb . sh/embed/32c 9 uev 8 hsj

如果这不起作用,这里有一个非交互式版本:

phone_numbers = { 'Jack': '070-02222748', 
                  'Pete': '010-2488634',
                  'Eric': '06-10101010' }
names = phone_numbers.keys()
numbers = phone_numbers.values()
phone_numbers['Linda'] = '030-987612312'
print(names)
print(numbers)

# Loop through a view object with:
for number in numbers:
    print(number)

这段代码的输出是dict_keys(['Jack', 'Pete', 'Eric', 'Linda'])。如您所见Linda 也是列表的一部分,尽管她是在创建了names视图对象之后添加的。

dict.items():遍历 Python 字典

字典的items()方法返回一个 iterable view 对象,提供键和值,如下所示。您可以用一个简单的 Python for-loop 遍历这个对象:

>>> phone_numbers.items()
dict_items([('Jack', '070-02222748'), 
            ('Pete', '010-2488634'), 
            ('Eric', '06-10101010')])
>>> for name, phonenr in phone_numbers.items():
...     print(name, ":", phonenr)
...
Jack : 070-02222748
Pete : 010-2488634
Eric : 06-10101010

或者,您可以使用keys()values()方法只遍历键或值。这两个函数都返回一个可迭代的视图对象。

获得所有钥匙的更多方法

我们已经看到了dict.keys()方法,它返回一个包含所有字典键列表的视图对象。这个对象的优点是它与字典保持同步。它非常适合循环所有的键,但是您仍然可以选择listsorted方法,因为它们返回一个您也可以操作的原生列表。

还有两种简单的方法可以从字典中获取所有的键:

>>> phone_numbers = { 'Jack': '070-02222748', 
                      'Pete': '010-2488634', 
                      'Eric': '06-10101010' }
>>> list(phone_numbers)
['Jack', 'Pete', 'Eric']
>>> sorted(phone_numbers)
['Eric', 'Jack', 'Pete']

list()返回按插入顺序排列的所有键,而sorted()返回按字母顺序排列的所有键。

合并字典

如果您运行的是 Python 3.9 或更高版本,则可以对字典使用新引入的合并运算符:

merged = dict1 | dict2

如果您仍然使用 3.5 到 3.9 之间的 Python 版本,可以使用以下方法合并两个字典:

dict1 = { 'a': 1, 'b': 2 }
dict2 = { 'b': 3, 'c': 4 }
merged = { **dict1, **dict2 }
print (merged)
# {'a': 1, 'b': 3, 'c': 4}

比较 Python 字典

如果您需要比较两个字典,您可以简单地使用比较运算符,如下所示:

>>> first_dict  = { 'a': 1, 'b': 2, 'c': 'a string' }
>>> second_dict = { 'a': 1, 'b': 2, 'c': 'a string' }
>>> first_dict == second_dict
True

这看起来和听起来都很琐碎其实不然毕竟字典可以包含任何类型的对象因此Python 必须遍历所有的键和值,并逐个比较它们。

您可能想知道,具有相同键和值的字典,以另一种顺序插入,是否是相同的。让我们看看这个:

>>> first_dict  = { 'a': 1, 'b': 2, 'c': 'a string' }
>>> second_dict  = { 'b': 2, 'a': 1, 'c': 'a string' }
>>> first_dict == second_dict
True

它们与 Python 是一样的,尽管顺序不同。

注意:从 Python 3.7 开始,字典的顺序保证是插入顺序。换句话说,这意味着字典的顺序是由您插入条目的顺序决定的。

内置 Python 字典方法

每个字典都继承了许多方便的内置函数,如下表所示:

方法 什么是做 例子
clear() 删除所有键/值对(清空字典) phone_numbers.clear()
get(key) 用给定的键和可选的默认值获取单个项目 phone_numbers.get('Martha', 'Unknown person')
items() 从字典中返回包含键值对的视图对象 phone_numbers.items()
keys() 返回一个视图对象,其中包含字典中所有键的列表 phone_numbers.keys()
values() 返回一个 view_object其中包含字典中所有值的列表 phone_numbers.values()
pop(key, default_value) 返回并移除具有指定键的元素 phone_numbers.pop('Martha')
popitem() 返回并移除最后插入的项目(Python 3.7 以上)或随机项目 phone_numbers.popitem()
setdefault(key, value) 返回指定键的值。如果键不存在,则插入给定值 phone_numbers.setdefault('John Doe', 1234)
update(iterable) 从给定的 iterable(例如字典)中添加所有对 phone_numbers.update({"Alina": 1234, "Alice", 2345})

Python 字典的内置方法

结论

您已经学习了什么是 Python 字典,如何创建字典,以及如何使用它们。我们已经用示例代码查看了许多涉及 Python 字典的实际用例。如果还缺少什么,或者只是想了解更多关于字典的知识,你可以去 Python.org 的官方手册页。