带有字典和 abc.Mapping 的 isinstance 从集合中做什么?

问题描述 投票:0回答:3

我正在运行的代码是:

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

我明白

isinstance
的作用,但我不确定
abc.Mapping
collections
的作用是什么?

看起来

isinstance(mydict, abc.Mapping)
行被用来检查
mydict
是一本字典吗?

这样不是更容易做到吗

isinstance(mydict, dict)

我做了一些搜索并在此线程中找到了相关评论:What is the best (idiomatic) way to check the type of a Python variable?,但我仍然无法弄清楚为什么在这里使用

abc.Mapping
更可取不仅仅是使用
dict

python dictionary abstract-base-class
3个回答
30
投票

collections.abc 为容器提供了一系列抽象基类。

该模块提供了抽象基类,可以用来测试一个类是否提供了特定的接口;例如,它是否可散列或是否是映射。

它们允许您检查某个对象是否具有与您正在检查的 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
然后你的另一个朋友需要......看到这里的模式了吗?我提到的所有对象(列表、元组、双端队列)都有相同的共同点,并且可以通过该示例函数以相同的方式使用。 所有这些行为都被压缩在 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']
>>> 

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


12
投票

collections.abc
模块提供了几个抽象基类,可用于通用描述Python中的各种数据结构。在您的示例中,您测试一个对象是否是
Mapping
抽象类的实例,这对于许多“像字典一样工作”的类来说都是如此(例如,它们有一个
__getitem__
方法,该方法采用可哈希键和返回值,有
keys
values
items
方法等)。这种类似
dict
的对象可能会继承自
dict
,但它们不需要。

collections.abc
中的抽象类型是使用顶级
abc
模块
实现的。
dict
register
编辑为
MutableMapping
(它是
Mapping
的子类),因此
isinstance
检查将接受字典作为
Mapping
,即使
Mapping
不是实际的基础
dict
的课程。


5
投票

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

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

© www.soinside.com 2019 - 2024. All rights reserved.