wim*_*wim 6 python cpython python-2.7
>>> 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
Run Code Online (Sandbox Code Playgroud)
为什么对getslice的调用不尊重stop我发送的内容,而是默默地替换2 ^ 63 - 1?这是否意味着__getslice__为您自己的语法实现通常是不安全的长期?
__getitem__无论如何,我可以做任何我需要的事情,我只是想知道为什么__getslice__显然会被打破.
编辑: CPython中截断切片的代码在哪里?这是python(语言)规范的一部分还是cpython(实现)的"特性"?
处理实现sq_slice插槽的对象的切片的Python C代码无法处理Py_ssize_t(== sys.maxsize)上的任何整数.该sq_slice槽是的C-API等效__getslice__特殊方法.
对于双元素切片,Python 2使用其中一个SLICE+*操作码 ; 然后由apply_slice()函数处理.这使用_PyEval_SliceIndex函数来Python的索引对象转换(int,long,或任何实施__index__方法)至一个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.
*/
Run Code Online (Sandbox Code Playgroud)
这意味着使用2值语法在Python 2中进行的任何切片都限于提供插槽sys.maxsize时范围内的值sq_slice.
使用三值form(item[start:stop:stride])进行切片会改为使用BUILD_SLICE操作码(后跟BINARY_SUBSCR),而是创建一个不限制的slice()对象sys.maxsize.
如果对象没有实现sq_slice()槽(因此不__getslice__存在),则该apply_slice()函数也会回退到使用slice()对象.
至于这是一个实现细节或语言的一部分:Slicings表达文档区分simple_slicing和extended_slicing; 前者只允许short_slice表格.对于简单切片,索引必须是普通整数:
下限和上限表达式(如果存在)必须求值为普通整数; 默认值分别为零和
sys.maxint.
这表明 Python 2 语言将索引限制为sys.maxint值,不允许长整数.在Python 3中,简单的切片已完全从语言中删除.
如果您的代码必须支持使用超出值的切片,sys.maxsize 并且您必须从实现的类型继承,__getslice__那么您的选项是:
使用三值语法,None对于步幅:
Potato()[123:x:None]
Run Code Online (Sandbox Code Playgroud)slice()明确创建对象:
Potato()[slice(123, x)]
Run Code Online (Sandbox Code Playgroud)slice()对象可以long很好地处理整数; 但是该slice.indices()方法无法处理长度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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
142 次 |
| 最近记录: |