Python iInstance使用字典和集合的abc.Mapping做什么?

Python iInstance使用字典和集合的abc.Mapping做什么?,python,dictionary,abstract-base-class,Python,Dictionary,Abstract Base Class,我正在运行的代码是: >>> from collections import abc >>> mydict = {'test_key': 'test_value'} >>> isinstance(mydict, abc.Mapping) True 我了解isinstance的功能,但不确定abc.Mapping在集合中的功能 似乎有一行isinstance(mydict,abc.Mapping)被用来检查mydict是否是字典 这不是更容易

我正在运行的代码是:

>>> from collections import abc
>>> mydict = {'test_key': 'test_value'}
>>> isinstance(mydict, abc.Mapping)
True
我了解isinstance的功能,但不确定abc.Mapping在集合中的功能

似乎有一行
isinstance(mydict,abc.Mapping)
被用来检查
mydict
是否是字典

这不是更容易做到吗
isinstance(mydict,dict)


我做了一些搜索,并在这个线程中找到了相关的注释:,但我仍然很难弄清楚为什么使用
abc.Mapping
比只使用
dict

集合更可取。abc.Mapping
更可取,因为它为这种类型的容器定义了抽象api,因为dict
只是这样一个容器的实现。有点过于简单,但这是关键-
dict
不是一个接口/abstract/api/


非dict实例的对象示例广泛用于web框架(例如aiohttp)。

集合。abc模块提供了几个抽象基类,可用于在Python中一般描述各种数据结构。在您的示例中,您测试一个对象是否是
映射
抽象类的实例,这对于许多“像字典一样工作”的类来说都是正确的(例如,它们有一个
\uuuu getitem\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。此类类似于
dict
的对象可能继承自
dict
,但它们不需要继承

collections.abc
中的抽象类型是使用实现的
dict
寄存器
作为
可变映射
(它是
映射的子类
)因此,
isinstance
检查将接受字典作为
映射
,即使
映射
不是
dict
的实际基类

为容器提供了一系列抽象基类

该模块提供抽象基类,可用于测试类是否提供特定接口;例如,它是可散列的还是映射的

它们允许您检查某个对象是否具有与您正在检查的ABC类似的行为,而无需关心实际实现

例如,假设你有一个函数F,它根据参数的类型做一些事情,你可以直接检查它是否是list或tuple或dict等的实例,然后做你的工作,但这限制了你只需要使用它们,如果你自己的类有类似的行为,比如说list,在某些情况下你关心,如果你想把它和F一起使用,你发现它不起作用,那么你必须修改F来接受你的类,但是如果你用ABC来检查,那么这样的修改是不必要的

现在是一个有效的例子:假设您想要一个函数,该函数将列表中的所有元素置于偶数位置,那么您就可以这样做了

def even_pos(data):
    if isinstance(data,list):
        return [data[i] for i in range(0,len(data),2)]
    else:
        raise ValueError("only a list")
并用作

>>> test = list(range(20))
>>> even_pos(test)
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
>>>
这没问题,但当你意识到元组与this函数中的列表相同时,你也可以将检查添加到函数中,一切都很好,但是你的朋友告诉你他想使用你的函数,但他使用的是集合。deque
,然后你的另一个朋友告诉你。。。看到这里的图案了吗?我提到的所有对象(list、tuple、deque)都有相同的共同点,并且可以通过该示例函数以相同的方式使用,并且所有这些行为都在ABC中压缩,因此,您只需要
isinstance(data,ABC.Sequence),而不是
isinstance(data,(list、tuple、collections.deque,…)
isinstance(data,ABC.Sequence)
该函数如下所示

from collections import abc
def even_pos(data):
    if isinstance(data,abc.Sequence):
        return [data[i] for i in range(0,len(data),2)]
    else:
        raise ValueError("only a Sequence")

>>> even_pos( list(range(10)) )
[0, 2, 4, 6, 8]
>>> even_pos( tuple(range(10)) )
[0, 2, 4, 6, 8]
>>> even_pos( range(10) )  # in python 3 range don't return a list, but a range object
[0, 2, 4, 6, 8]
>>> even_pos( "asdfghjh" )
['a', 'd', 'g', 'j']
>>> 

现在,您不需要知道正在使用的实际实现,只需要知道它具有您想要的行为

这是一个比公认的更好的答案,因为它提到collections.abc.Mapping不是dict的实际基类(您可以通过查看dict来检查这一点)。如果能更好地解释“dict注册为可变映射”意味着什么,
register
方法记录在我链接的页面上,那就更好了。下面是具体说明。