【Python进阶】为何使用isinstance检查抽象基类接口比直接检查dict类型更优

“使用isinstance测试是否满足抽象基类的接口要求,往往比检查一个函数的参数是不是具体的dict类型要好,因为除了dict之外还有其他映射类型可用”,这段话出自《流畅的Python》第二版上册第3.4节“映射类型的标准API”中的“提示”。

这段话的意思是,使用 isinstance 来测试对象是否符合某个抽象基类(ABC)的接口要求,比直接检查对象是否是某个具体类型(例如 dict)更为灵活和通用。

让我们逐步分析这段话的含义:

一. isinstance 和抽象基类接口要求

抽象基类(ABC)是Python中用于定义接口的工具,它允许我们指定一个类必须实现的某些方法(抽象方法)。当使用 isinstance 来检查一个对象时,它不仅会检查对象是否是某个具体类的实例,还会检查它是否实现了该类所定义的接口(即继承关系)。

例如,假设你有一个抽象基类 Mapping(它可能是 collections.abc.Mapping)定义了字典的接口方法,如 getitem, iter, 和 len,你可以通过 isinstance 来检查一个对象是否是符合 Mapping 接口的实现。这样,即使这个对象不是具体的 dict 类型,只要它实现了这些方法,它就可以被认为是一个“字典类型”,也能通过 isinstance 检查。

from collections.abc import Mapping

#### 自定义一个类,模拟字典行为
class MyMapping(Mapping):
    def __getitem__(self, key):
        return "some value"
    
    def __iter__(self):
        return iter(["key1", "key2"])
    
    def __len__(self):
        return 2

obj = MyMapping()
print(isinstance(obj, Mapping))  # True

二. 直接检查 dict 类型的局限性

如果你仅仅检查一个对象是否是具体的 dict 类型(即 isinstance(obj, dict)),你只会识别出标准的字典对象,而无法识别其他也实现了字典行为的对象。例如,如果你定义了一个自定义类,它实现了字典接口的所有方法(比如 getitem, iter, 和 len),但是它不是标准的 dict 类型,那么通过 isinstance(obj, dict) 就无法识别它。

这就是为什么直接检查一个函数的参数是不是具体的 dict 类型可能不够灵活。因为 除了标准的 dict 类型,还有其他可以作为“映射类型”的对象,例如自定义的类,或是来自第三方库的类,它们实现了字典的接口,但不是 dict 类型。使用抽象基类(如 Mapping)可以帮助你更广泛地匹配符合接口要求的对象,而不仅仅是 dict。

三. 其他映射类型的可用性

dict 是一个典型的映射类型,但在Python中,映射类型不仅仅限于 dict。实际上,Python的标准库提供了多个实现了类似字典行为的类型,例如:

collections.defaultdict: 这是一个特殊的字典,它允许你为不存在的键设置默认值。
collections.OrderedDict: 这是一个有序字典,它保留插入顺序。
自定义的类:你可以实现一个自定义类,按照映射类型的接口来设计,比如支持通过键访问值。
通过 Mapping 这样的抽象基类,你不仅能匹配 dict 类型,还能匹配所有符合映射接口的对象,而不需要关心它们的具体类型。

四. 总结

这段话的核心意思是,通过抽象基类(例如 Mapping)和 isinstance 来测试对象是否实现了某个接口,比直接检查对象是否是某个具体类型(如 dict)更具灵活性。因为实现了特定接口的对象不仅限于某个具体类型,使用抽象基类可以让你更普遍地检查对象的接口,而不局限于某种实现类型。

例如,代码中的自定义类 MyMapping,虽然它不是 dict 类型,但它实现了字典的行为,使用 Mapping 抽象基类就能让你正确识别它是一个符合字典接口的对象。

基础扩展:
Mapping 是 dict 的父类。Mapping 是一个抽象基类,定义了字典类型应具备的一些核心接口(如 getitemiterlen),而 dict 是 Mapping 的一个具体实现。所以,dict 继承自 Mapping,并且满足 Mapping 的接口要求。

扩展阅读:【python进阶】基类、元类以及一些相关的概念如抽象类和接口

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值