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 次 |
最近记录: |