简体   繁体   English

什么是字典和abc.Mapping从集合做什么?

[英]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.Mappingcollections什么?

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__方法,它接受可以使用的密钥和返回值,有keysvaluesitems方法等)。 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 . dictregisterMutableMapping (它是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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM