Python iInstance使用字典和集合的abc.Mapping做什么?
我正在运行的代码是:Python iInstance使用字典和集合的abc.Mapping做什么?,python,dictionary,abstract-base-class,Python,Dictionary,Abstract Base Class,我正在运行的代码是: >>> from collections import abc >>> mydict = {'test_key': 'test_value'} >>> isinstance(mydict, abc.Mapping) True 我了解isinstance的功能,但不确定abc.Mapping在集合中的功能 似乎有一行isinstance(mydict,abc.Mapping)被用来检查mydict是否是字典 这不是更容易
>>> from collections import abc
>>> mydict = {'test_key': 'test_value'}
>>> isinstance(mydict, abc.Mapping)
True
我了解isinstance的功能,但不确定abc.Mapping在集合中的功能
似乎有一行isinstance(mydict,abc.Mapping)
被用来检查mydict
是否是字典
这不是更容易做到吗
isinstance(mydict,dict)
我做了一些搜索,并在这个线程中找到了相关的注释:,但我仍然很难弄清楚为什么使用
abc.Mapping
比只使用dict集合更可取。abc.Mapping
更可取,因为它为这种类型的容器定义了抽象api,因为dict
只是这样一个容器的实现。有点过于简单,但这是关键-dict
不是一个接口/abstract/api/
非dict实例的对象示例广泛用于web框架(例如aiohttp)。集合。abc模块提供了几个抽象基类,可用于在Python中一般描述各种数据结构。在您的示例中,您测试一个对象是否是
映射
抽象类的实例,这对于许多“像字典一样工作”的类来说都是正确的(例如,它们有一个\uuuu getitem\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。此类类似于dict
的对象可能继承自dict
,但它们不需要继承
collections.abc
中的抽象类型是使用实现的dict
是寄存器
作为可变映射
(它是映射的子类
)因此,isinstance
检查将接受字典作为映射
,即使映射
不是dict
的实际基类为容器提供了一系列抽象基类
该模块提供抽象基类,可用于测试类是否提供特定接口;例如,它是可散列的还是映射的
它们允许您检查某个对象是否具有与您正在检查的ABC类似的行为,而无需关心实际实现
例如,假设你有一个函数F,它根据参数的类型做一些事情,你可以直接检查它是否是list或tuple或dict等的实例,然后做你的工作,但这限制了你只需要使用它们,如果你自己的类有类似的行为,比如说list,在某些情况下你关心,如果你想把它和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]
>>>
这没问题,但当你意识到元组与this函数中的列表相同时,你也可以将检查添加到函数中,一切都很好,但是你的朋友告诉你他想使用你的函数,但他使用的是集合。deque
,然后你的另一个朋友告诉你。。。看到这里的图案了吗?我提到的所有对象(list、tuple、deque)都有相同的共同点,并且可以通过该示例函数以相同的方式使用,并且所有这些行为都在ABC中压缩,因此,您只需要isinstance(data,ABC.Sequence),而不是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.Mapping不是dict的实际基类(您可以通过查看dict来检查这一点)。如果能更好地解释“dict注册为可变映射”意味着什么,
register
方法记录在我链接的页面上,那就更好了。下面是具体说明。