什么是字典和abc.Mapping从集合做什么?

Vin*_*ent 8 python dictionary

我正在运行的代码是:

>>> from collections import abc
>>> mydict = {'test_key': 'test_value'}
>>> isinstance(mydict, abc.Mapping)
True
Run Code Online (Sandbox Code Playgroud)

我明白了什么isinstance呢,但我不知道是什么abc.Mapping的呢collections

好像这条线isinstance(mydict, abc.Mapping)被用来检查那mydict是一本字典?

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

我做了一些搜索并在这个帖子中找到了相关的注释:检查Python变量类型的最佳(惯用)方法是什么?,但我仍然无法弄清楚为什么abc.Mapping在这里使用比使用更好dict.

Cop*_*eld 10

collections.abc为容器提供了一系列Abstract Base Classes

该模块提供了抽象基类,可用于测试类是否提供特定接口; 例如,它是否可以清除或是否是映射.

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

例如,假设您有一个函数F根据参数的类型执行某些操作,您可以直接检查是否是列表或元组或字典等的实例,并完成您的工作,但这限制了您只有使用那些,如果你然后使自己的类具有类似的行为来说出一个列表,在某些情况下你关心,并想要用它与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")
Run Code Online (Sandbox Code Playgroud)

并用作

>>> test = list(range(20))
>>> even_pos(test)
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
>>>
Run Code Online (Sandbox Code Playgroud)

没有问题,但是你意识到一个元组与这个函数关注的列表是一样的,你可以将该检查添加到函数中,一切都很好,但是然后你的朋友告诉你他想用你的功能,但他正在使用一个collections.deque,然后你的另一个朋友告诉...看到这里的模式?我提到的所有对象(list,tuple,deque)都有相同的东西,并且可以通过该示例函数以相同的方式使用,并且所有这些行为都是在ABC中压缩,所以代替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']
>>> 
Run Code Online (Sandbox Code Playgroud)

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


Blc*_*ght 7

collections.abc模块提供了几个抽象基类,可用于一般性地描述 Python 中的各种数据结构。在你的榜样,你测试如果对象是实例Mapping抽象类,这将是真正的许多类,“工作像一本字典”(例如他们有__getitem__这需要可哈希键和返回值,有方法keysvaluesitems方法,等等。)。这种dict类似的对象可能会继承,dict但它们不需要。

中的抽象类型collections.abc是使用顶级abc模块实现的dictregister编辑为 a MutableMapping(这是Mapping),因此isinstance检查将接受字典作为 aMapping即使Mapping不是 的实际基类dict


kwa*_*nek 5

collections.abc.Mapping是首选,因为它为此类容器定义了抽象 api,因为dict它只是此类容器的实现。有点过于简单化,但这是关键 -dict不是接口/抽象/api/...

非 dict 实例的对象示例是MultiDict,广泛用于 Web 框架(例如 aiohttp)。