[英]What does isinstance with a dictionary and abc.Mapping from collections doing?
The code I'm running is: 我正在运行的代码是:
>>> from collections import abc
>>> mydict = {'test_key': 'test_value'}
>>> isinstance(mydict, abc.Mapping)
True
I understand what isinstance
does, but I'm not sure what abc.Mapping
does from collections
? 我理解
isinstance
作用,但我不确定abc.Mapping
从collections
什么?
It seems like the line isinstance(mydict, abc.Mapping)
is being used to check that mydict
is a dictionary? 似乎行
isinstance(mydict, abc.Mapping)
用于检查mydict
是否是字典?
Wouldn't it just be easier to do isinstance(mydict, dict)
? 是不是更容易做
isinstance(mydict, dict)
?
I did some searching and found related comments in this thread: What is the best (idiomatic) way to check the type of a Python variable? 我做了一些搜索并在这个帖子中找到了相关的注释: 检查Python变量类型的最佳(惯用)方法是什么? , but I'm still having trouble figuring out why using
abc.Mapping
is preferable here than just using dict
. ,但我仍然无法弄清楚为什么使用
abc.Mapping
比使用dict
更可取。
collections.abc provide a serie of Abstract Base Classes for container collections.abc为容器提供了一系列Abstract Base Classes
This module provides abstract base classes that can be used to test whether a class provides a particular interface;
该模块提供了抽象基类,可用于测试类是否提供特定接口; for example, whether it is hashable or whether it is a mapping.
例如,它是否可以清除或是否是映射。
they allow you to check if a certain object have a behavior similar to that of the ABC you are checking without care for the actual implementation. 它们允许您检查某个对象是否具有与您正在检查的ABC类似的行为,而无需关心实际实现。
For example, say that you have a function F that do something according to the type of the argument, you can check if is a instance of list or tuple or dict or etc directly, and do your job, but that limit you to only have to use those, if you then make your own class that have a similar behavior to say a list, in some case you care about, and want to use it with F, you find it don't work, then you have to modify F to accept your class, but if instead you check against an ABC such modification is unneeded 例如,假设您有一个函数F根据参数的类型执行某些操作,您可以直接检查是否是列表或元组或字典等的实例,并完成您的工作,但这限制了您只有使用那些,如果你然后使自己的类具有类似的行为来表示列表,在某些情况下你关心,并且想要与F一起使用它,你发现它不起作用,那么你必须修改F接受你的班级,但如果你反对ABC检查这种修改是不必要的
Now a working example: say that you want a function that give all the elements in even position from a list, then you can do 现在是一个工作示例:假设您需要一个函数,从列表中为所有元素提供偶数位置,那么您可以这样做
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")
and use as 并用作
>>> test = list(range(20))
>>> even_pos(test)
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
>>>
no problem there, but then you realize that a tuple is the same that a list in what a this function concern, you can add that check to the function too, and everything is fine, but then your friend told you he want to use your function but he is using a collections.deque
and then your other friend told... see the pattern here? 没有问题,但是你意识到一个元组与这个函数关注的列表是一样的,你可以将该检查添加到函数中,一切都很好,但是然后你的朋友告诉你他想用你的功能,但他正在使用
collections.deque
然后你的另一个朋友告诉...看到这里的模式? all the object that I mention (list, tuple, deque) have in common the same thing, and can be used in the same way by that example function, and all that behavior is compress in the ABC, so instead of isinstance(data,(list,tuple,collections.deque,...)
you only need isinstance(data,abc.Sequence)
and the function looks like 我提到的所有对象(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']
>>>
Now you don't need to know the actual implementation that is in use, only that it have the behavior that you want 现在,您不需要知道正在使用的实际实现,只需知道它具有您想要的行为
The collections.abc
module provides several abstract base classes that can be used to generically describe the various kinds of data structures in Python. collections.abc
模块提供了几个抽象基类,可用于在Python中一般性地描述各种数据结构。 In your example, you test if an object is an instance of the Mapping
abstract class, which will be true for many classes that "work like a dictionary" (eg they have a __getitem__
method that takes hashable keys and return values, have keys
, values
and items
methods, etc.). 在您的示例中,您测试一个对象是否是
Mapping
抽象类的一个实例,对于许多“像字典一样工作”的类(例如,他们有一个__getitem__
方法,它接受可以使用的密钥和返回值,有keys
, values
和items
方法等)。 Such dict
-like objects might inherit from dict
but they don't need to. 这类
dict
的对象可能继承自dict
但它们并不需要。
The abstract types in collections.abc
are implemented using the top level abc
module . collections.abc
中的抽象类型是使用顶级abc
模块实现的 。 dict
is register
ed as a MutableMapping
(which is a subclass of Mapping
) and so the isinstance
check will accept a dictionary as a Mapping
even though Mapping
isn't an actual base class for dict
. dict
被register
为MutableMapping
(它是Mapping
的子类),因此即使Mapping
不是dict
的实际基类, isinstance
检查也会接受字典作为Mapping
。
collections.abc.Mapping
is preferred because it defines abstract api for this type of containers , since dict
is only an implementation of such a container. collections.abc.Mapping
是首选,因为它为这种类型的容器定义了抽象api ,因为dict
只是这种容器的一个实现。 Is a bit oversimplified, but this is the key - dict
is not an interface/abstract/api/... 有点过于简单,但这是关键 -
dict
不是接口/ abstract / api / ...
The example of objects that are not a dict instances are MultiDict , widely used in web frameworks (eg aiohttp). 不是dict实例的对象示例是MultiDict ,广泛用于Web框架(例如aiohttp)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.