我正在运行的代码是:
>>> 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)
现在,您不需要知道正在使用的实际实现,只需知道它具有您想要的行为
这 collections.abc模块提供了几个抽象基类,可用于一般性地描述 Python 中的各种数据结构。在你的榜样,你测试如果对象是实例Mapping抽象类,这将是真正的许多类,“工作像一本字典”(例如他们有__getitem__这需要可哈希键和返回值,有方法keys,values和items方法,等等。)。这种dict类似的对象可能会继承,dict但它们不需要。
中的抽象类型collections.abc是使用顶级abc模块实现的。dict被register编辑为 a MutableMapping(这是Mapping),因此isinstance检查将接受字典作为 aMapping即使Mapping不是 的实际基类dict。