我们经常在代码中使用一些映射类型(如字典、默认字典、排序字典等),但在许多情况下,如何理解它们之间的继承关系,以及它们如何在父类的基础上扩展出更多的功能,可能会让我们感到困惑。为了写出高质量的类型提示,尤其是遵循伯斯塔尔定律(发送时要保守,接收时要大方),理解这些映射类型的继承结构是非常重要的。本篇文章将深入分析 Python 中的映射类型、它们的父类关系,以及如何在类型提示中应用这些映射类型的知识。
(本文加粗方法均为双下划线开头结尾的方法,由于编辑器原因显示为加粗)
一、Python中的映射类型
在 Python 中,映射类型指的是那些将键(key)映射到值(value)上的数据结构。最常见的映射类型是 dict,但除此之外,Python 还提供了多种映射相关的数据结构,用于满足不同的需求。以下是一些常见的映射类型:
1、dict:
最基本的映射类型,支持键值对存储。Python中的 dict 可以通过键来存储和访问值,并且是无序的(在 Python 3.7+ 版本中,字典维护插入顺序)。
2、defaultdict:
defaultdict 是 Python 的 collections 模块提供的一个字典子类,它为字典中不存在的键提供默认值。这使得在访问不存在的键时不抛出异常,而是返回一个指定的默认值。
3、OrderedDict:
OrderedDict 也是 dict 的一个子类,扩展了 dict 的功能,维护了键值对的插入顺序。在 Python 3.7 之后,标准的 dict 已经保持了插入顺序,但 OrderedDict 仍然有一些在性能优化方面的优势,尤其是在一些特定场景下(如频繁进行字典排序操作时)。
4、Mapping:
Mapping 是 Python 标准库 collections.abc 中的一个抽象基类,用于定义所有映射类型。通过继承 Mapping 类,可以创建自定义的映射类型。Mapping 定义了最基本的映射操作接口,如__getitem__、iter__和__len
5、MappingProxyType:
MappingProxyType 是 types 模块提供的一个类,它可以将一个字典或其他映射类型转换为一个只读的映射视图,使得原字典的内容不可被修改。
二、映射类型的继承关系和扩展功能
理解映射类型的继承关系,有助于我们更好地使用这些类型,尤其是在自定义映射类型时。我们可以通过继承现有的映射类型,实现新的功能或定制行为。以下是 Python 中常见的映射类型及其继承关系的详细分析:
1、Mapping 类:抽象基类
Mapping 是 Python 中所有映射类型的抽象基类。它实现了常见的映射操作,并为所有映射类型提供了一个统一的接口。Mapping 的父类为 Iterable 和 Sized,这意味着所有继承 Mapping 的类型都必须实现可迭代和大小操作。具体来说,Mapping 定义了以下核心方法:
getitem(self, key):通过键获取值。
iter(self):返回一个可以迭代的键集合。
len(self):返回映射的元素个数。
这些方法使得映射类型可以像字典一样被访问和遍历。例如,dict、OrderedDict 和 defaultdict 都继承了 Mapping 类,并提供了不同的扩展和实现。
2、dict 类:标准字典
dict 是 Python 中最常用的映射类型,它直接继承自 Mapping 类,并实现了 getitem、iter 和 len 等方法,此外还支持一些字典特有的操作,如 setitem(添加或更新键值对)和 delitem(删除键值对)。在 Python 3.7 及以后版本中,dict 还保证了键值对的插入顺序。
3、defaultdict 类:提供默认值的字典
defaultdict 是 dict 的子类,它扩展了 dict 的功能,提供了一个 default_factory 参数,允许为不存在的键自动生成默认值。当访问一个不存在的键时,defaultdict 会调用 default_factory 提供的函数或工厂来生成默认值,而不是抛出 KeyError 异常。这样可以避免写大量的检查是否存在键的代码。
继承关系:
object -> Mapping -> dict -> defaultdict
4、OrderedDict 类:有序字典
OrderedDict 是 dict 的一个子类,扩展了字典的一些行为。最显著的特点是,OrderedDict 会记住键值对的插入顺序,允许按插入顺序遍历字典中的键值对。尽管从 Python 3.7 开始,标准的 dict 也保证了插入顺序,但 OrderedDict 提供了更多特性,如 move_to_end(),可以让你在字典中重新排列键值对的顺序。
继承关系:
object -> Mapping -> dict -> OrderedDict
5、MappingProxyType:只读映射视图
MappingProxyType 是 types 模块中的一个类,它可以将一个字典或其他映射类型转换为一个只读视图。在这个视图中,所有对字典的修改操作都会抛出 TypeError 异常,确保映射内容不被修改。
继承关系:
object -> Mapping -> MappingProxyType
三、映射类型在类型提示中的应用
在 Python 的类型提示中,映射类型的使用非常广泛,尤其是在处理复杂数据结构时,理解如何利用 Mapping 以及其子类进行类型注解变得尤为重要。
1、使用 Mapping 进行类型注解
Mapping 可以作为一个通用的类型提示,表示任意一个映射类型,无论是 dict、defaultdict 还是 OrderedDict。如果你需要接受一个任何类型的映射(比如字典或其子类),你可以使用 Mapping 作为类型注解。
例如:
from collections.abc import Mapping
def print_mapping(mapping: Mapping[str, int]) -> None:
for key, value in mapping.items():
print(f"{key}: {value}")
在这个例子中,mapping 参数被注解为 Mapping[str, int],表示它是一个键为字符串、值为整数的映射。无论传入的是 dict、OrderedDict 还是 defaultdict,函数都能正确处理。
2、使用具体的映射类型
当你明确知道函数参数的映射类型时,通常可以直接使用具体的类型,如 dict、defaultdict 或 OrderedDict。例如,若你需要一个特定类型的字典,可以直接使用 dict 类型注解。
from collections import defaultdict
def process_defaultdict(mapping: defaultdict[str, int]) -> None:
# 使用默认字典处理逻辑
pass
3、使用 MappingProxyType 创建只读映射
在某些场合下,我们可能需要创建一个只读的映射类型视图,可以使用 MappingProxyType 来创建一个不可修改的映射视图。在类型注解中,我们可以使用 Mapping 来标明它是一个只读映射。
from types import MappingProxyType
def read_only_mapping(mapping: Mapping[str, int]) -> MappingProxyType:
return MappingProxyType(mapping)
总结
通过理解 Python 中的映射类型及其继承关系,我们不仅能够更好地理解 dict、OrderedDict、defaultdict 等类型的功能差异,还能在类型提示中更加精准地表达我们希望接受的类型。这种理解能够帮助我们在代码中严格区分不同类型的映射,避免不必要的错误,并提高代码的可读性和可维护性。
872

被折叠的 条评论
为什么被折叠?



