什么是Python的序列协议? [英] What is Python's sequence protocol?

查看:128
本文介绍了什么是Python的序列协议?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Python在魔术方法上做了很多事情,其中​​大多数是某些协议的一部分。我熟悉迭代器协议和数字协议,但最近偶然发现了序列协议 。但是即使经过一些研究,我也不确定顺序协议是什么。

Python does a lot with magic methods and most of these are part of some protocol. I am familiar with the "iterator protocol" and the "number protocol" but recently stumbled over the term "sequence protocol". But even after some research I'm not exactly sure what the "sequence protocol" is.

例如C API函数 PySequence_Check 检查(根据文档)是否有对象实现序列协议。 源代码表示这是一个不属于字典,但实现了 __ getitem __ 方法,该方法与 iter 也指出:

For example the C API function PySequence_Check checks (according to the documentation) if some object implements the "sequence protocol". The source code indicates that this is a class that's not a dict but implements a __getitem__ method which is roughly identical to what the documentation on iter also states:


[...]必须支持序列协议( __ getitem __()方法,其整数参数从0开始)。[...]

[...]must support the sequence protocol (the __getitem__() method with integer arguments starting at 0).[...]

但是以 0 开头的要求不是实现的在 PySequence_Check 中。

But the requirement to start with 0 isn't something that's "implemented" in PySequence_Check.

然后还有 collections.abc.Sequence 类型,基本上说实例必须实现 __ reversed __ __包含____ __ iter __ __ len __

但是根据该定义,实现序列协议的类不一定是序列,例如数据模型 和一个序列具有一个序列的抽象类garantuee长度。但是一个仅实现 __ getitem __ (通过 PySequence_Check 的类)在使用 len( an_instance_of_that_class)

But by that definition a class implementing the "sequence protocol" isn't necessarily a Sequence, for example the "data model" and the abstract class garantuee that a sequence has a length. But a class just implementing __getitem__ (passing the PySequence_Check) throws an exception when using len(an_instance_of_that_class).

有人可以为我澄清一下序列和序列协议之间的区别吗(如果除了阅读之外还有协议的定义,源代码)以及何时使用哪个定义?

Could someone please clarify for me the difference between a sequence and the sequence protocol (if there's a definition for the protocol besides reading the source code) and when to use which definition?

推荐答案

这并不是真正的一致。

这里是 PySequence_Check

int
PySequence_Check(PyObject *s)
{
    if (PyDict_Check(s))
        return 0;
    return s != NULL && s->ob_type->tp_as_sequence &&
        s->ob_type->tp_as_sequence->sq_item != NULL;
}

PySequence_Check 检查是否对象提供了C序列协议,该协议是通过表示对象类型的 PyTypeObject 中的 tp_as_sequence 成员实现的。该 tp_as_sequence 成员是指向结构的指针,该结构包含用于序列行为的一堆函数,例如用于项目检索的 sq_item 通过数字索引和 sq_ass_item 进行项目分配。

PySequence_Check checks if an object provides the C sequence protocol, implemented through a tp_as_sequence member in the PyTypeObject representing the object's type. This tp_as_sequence member is a pointer to a struct containing a bunch of functions for sequence behavior, such as sq_item for item retrieval by numeric index and sq_ass_item for item assignment.

具体来说, PySequence_Check 要求其参数不是dict,并提供 sq_item

Specifically, PySequence_Check requires that its argument is not a dict, and that it provides sq_item.

类型为<用Python编写的code> __ getitem __ 会提供 sq_item ,无论它们是概念上的序列还是映射,因此用Python编写的映射不从 dict 继承的将通过 PySequence_Check

Types with a __getitem__ written in Python will provide sq_item regardless of whether they're conceptually sequences or mappings, so a mapping written in Python that doesn't inherit from dict will pass PySequence_Check.

另一方面, collections.abc.Sequence 仅检查对象是否具体地从集合继承.abc.Sequence 或是否通过 collections.abc.Sequence < register 显式注册其类(或超类)。 / code>。如果您只是自己执行序列而不做任何事情,则不会传递 isinstance(your_sequence,Sequence)。此外,大多数在 collections.abc.Sequence 中注册的类都不支持所有 collections.abc.Sequence 的类方法。总体而言, collections.abc.Sequence 的可靠性远不如人们通常期望的那样。

On the other hand, collections.abc.Sequence only checks whether an object concretely inherits from collections.abc.Sequence or whether its class (or a superclass) is explicitly registered with collections.abc.Sequence. If you just implement a sequence yourself without doing either of those things, it won't pass isinstance(your_sequence, Sequence). Also, most classes registered with collections.abc.Sequence don't support all of collections.abc.Sequence's methods. Overall, collections.abc.Sequence is a lot less reliable than people commonly expect it to be.

至于在实践中什么是序列,通常是支持 __ len __ __ getitem __ 的整数索引从0开始,不是映射。如果某个函数的文档说需要任何顺序,那几乎总是它所需要的。不幸的是,由于类似于很难确定的原因,很难测试不是映射。

As for what counts as a sequence in practice, it's usually anything that supports __len__ and __getitem__ with integer indexes starting at 0 and isn't a mapping. If the docs for a function say it takes any sequence, that's almost always all it needs. Unfortunately, "isn't a mapping" is hard to test for for reasons similar to how "is a sequence" is hard to pin down.

这篇关于什么是Python的序列协议?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆