繁体   English   中英

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

[英]What does isinstance with a dictionary and abc.Mapping from collections doing?

我正在运行的代码是:

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

我理解isinstance作用,但我不确定abc.Mappingcollections什么?

似乎行isinstance(mydict, abc.Mapping)用于检查mydict是否是字典?

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

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

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")

并用作

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

没有问题,但是你意识到一个元组与这个函数关注的列表是一样的,你可以将该检查添加到函数中,一切都很好,但是然后你的朋友告诉你他想用你的功能,但他正在使用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']
>>> 

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

collections.abc模块提供了几个抽象基类,可用于在Python中一般性地描述各种数据结构。 在您的示例中,您测试一个对象是否是Mapping抽象类的一个实例,对于许多“像字典一样工作”的类(例如,他们有一个__getitem__方法,它接受可以使用的密钥和返回值,有keysvaluesitems方法等)。 这类dict的对象可能继承自dict但它们并不需要。

collections.abc中的抽象类型是使用顶级abc模块实现的 dictregisterMutableMapping (它是Mapping的子类),因此即使Mapping不是dict的实际基类, isinstance检查也会接受字典作为Mapping

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM