gpt4 book ai didi

python - 切片端点被无形地截断

转载 作者:太空狗 更新时间:2023-10-29 22:30:20 26 4
gpt4 key购买 nike

>>> class Potato(object):
... def __getslice__(self, start, stop):
... print start, stop
...
>>> sys.maxint
9223372036854775807
>>> x = sys.maxint + 69
>>> print x
9223372036854775876
>>> Potato()[123:x]
123 9223372036854775807

为什么对 getslice 的调用不遵守我发送的 stop,而是默默地替换 2^63 - 1?这是否意味着为您自己的语法实现 __getslice__ 通常对 long 不安全?

无论如何,我可以用 __getitem__ 做任何我需要的事情,我只是想知道为什么 __getslice__ 显然坏了。

编辑: CPython 中截断切片的代码在哪里?这是 python(语言)规范的一部分还是只是 cpython(实现)的“功能”?

最佳答案

为实现 sq_slice 插槽的对象处理切片的 Python C 代码无法处理超过 Py_ssize_t 的任何整数 (== sys.maxsize) . sq_slice 槽是 C-API 等同于 __getslice__ 特殊方法。

对于二元素切片,Python 2 使用 SLICE+* opcodes 之一;然后由 apply_slice() function 处理。这使用 _PyEval_SliceIndex function 将 Python 索引对象(intlong 或任何实现 __index__ method 的对象)转换为 Py_ssize_t 整数。该方法具有以下注释:

/* Extract a slice index from a PyInt or PyLong or an object with the
nb_index slot defined, and store in *pi.
Silently reduce values larger than PY_SSIZE_T_MAX to PY_SSIZE_T_MAX,
and silently boost values less than -PY_SSIZE_T_MAX-1 to -PY_SSIZE_T_MAX-1.
Return 0 on error, 1 on success.
*/

这意味着当 sq_slice 提供插槽。

使用三值形式 (item[start:stop:stride]) 的切片使用 BUILD_SLICE opcode 代替(后跟 BINARY_SUBSCR ),这代替创建 slice() object 而不限于 sys。最大尺寸

如果对象没有实现 sq_slice() 槽(因此没有 __getslice__ 存在),apply_slice() 函数也会失效回到使用 slice() 对象。

至于这是实现细节还是语言的一部分:Slicings expression documentation 区分simple_slicingextended_slicing;前者只允许 short_slice 形式。对于简单切片,索引必须是普通整数:

The lower and upper bound expressions, if present, must evaluate to plain integers; defaults are zero and the sys.maxint, respectively.

表明 Python 2 语言 将索引限制为sys.maxint 值,不允许使用长整数。在 Python 3 中,简单切片已从语言中完全删除。

如果您的代码必须支持使用超过sys.maxsize 的值进行切片并且您必须从实现__getslice__ 的类型继承,那么您的选项是:

  • 使用三值语法,步长为None:

    Potato()[123:x:None]
  • 显式创建 slice() 对象:

    Potato()[slice(123, x)]

slice() 对象可以很好地处理 long 整数;然而 slice.indices() method 仍然无法处理超过 sys.maxsize 的长度:

>>> import sys
>>> s = slice(0, sys.maxsize + 1)
>>> s
slice(0, 9223372036854775808L, None)
>>> s.stop
9223372036854775808L
>>> s.indices(sys.maxsize + 2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: cannot fit 'long' into an index-sized integer

关于python - 切片端点被无形地截断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25597815/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com