![](/img/trans.png)
[英]Different results for `isinstance` with `collecitons.abc.Collection` and `collections.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.Mapping
从collections
什么?
似乎行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__
方法,它接受可以使用的密钥和返回值,有keys
, values
和items
方法等)。 这类dict
的对象可能继承自dict
但它们并不需要。
collections.abc
中的抽象类型是使用顶级abc
模块实现的 。 dict
被register
为MutableMapping
(它是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.