切片对象的最小表示

时间:2014-09-25 10:03:27

标签: python slice representation

是否有内置或简单的方法以某种方式表示切片对象,以便将表示放在括号中将导致相关的__getitem__解析表示与原始切片对象完全相同?实际上,我希望得到最小::符号,而不是slice(...)符号(尽管两者都有效)。

一个例子将澄清:我希望定义一个函数slice_repr,以便

slice_repr(slice(1, None))        ## Will return '1:'
slice_repr(slice(1, None, None))  ## Will return '1:'
slice_repr(slice(1, 10))          ## Will return '1:10'
slice_repr(slice(1, 10, None))    ## Will return '1:10'
slice_repr(slice(1, None, 3))     ## Will return '1::3'
slice_repr(slice(1, 10, 3))       ## Will return '1:10:3'
slice_repr(slice(10))             ## Will return ':10'
slice_repr(slice(None, 10))       ## Will return ':10'
slice_repr(slice(None, 10, 3))    ## Will return ':10:3'
slice_repr(slice(None, None, 3))  ## Will return '::3'

如果函数可以处理像

这样的输入,那就更好了
(slice(None, None, 3), Ellipsis, 3)

返回

'::3,...,3'

2 个答案:

答案 0 :(得分:1)

不适用于任意切片,可能包含任何内容,例如slice(object())

但如果你认为repr有效,你可以这样做:

def slice_slice_repr(slice_object):
    """
    Get the best guess of a minimal representation of
    a slice, as it would be created by indexexing.
    """
    slice_items = [slice_object.start, slice_object.stop, slice_object.step]

    if slice_items[-1] is None:
        slice_items.pop()

    if slice_items[-1] is None:
        return repr(slice_items[0]) + ":"

    else:
        return ":".join("" if x is None else repr(x) for x in  slice_items)

def arbitrary_slice_item_repr(object):
    """
    Get the best guess of a minimal representation of
    an item from an iterable recieved by __getitem__.
    """
    if type(object) is slice:
        return slice_slice_repr(object)

    elif object is Ellipsis:
        return "..."

    else:
        return repr(object)

def slice_repr(object):
    """
    Get the best guess of a minimal representation of
    an object recieved by __getitem__.
    """
    # Yes, "type(X) is Y" *is* the correct thing to do
    if type(object) is slice:
        return slice_slice_repr(object)

    if type(object) is tuple:
        return ",".join(map(arbitrary_slice_item_repr, object))

    else:
        return arbitrary_slice_item_repr(object)

slice_repr(slice(1, None))        ## Will return '1:'
slice_repr(slice(1, None, None))  ## Will return '1:'
slice_repr(slice(1, 10))          ## Will return '1:10'
slice_repr(slice(1, 10, None))    ## Will return '1:10'
slice_repr(slice(1, None, 3))     ## Will return '1::3'
slice_repr(slice(1, 10, 3))       ## Will return '1:10:3'
slice_repr(slice(10))             ## Will return ':10'
slice_repr(slice(None, 10))       ## Will return ':10'
slice_repr(slice(None, 10, 3))    ## Will return ':10:3'
slice_repr(slice(None, None, 3))  ## Will return '::3'
#>>> '1:'
#>>> '1:'
#>>> '1:10'
#>>> '1:10'
#>>> '1::3'
#>>> '1:10:3'
#>>> ':10'
#>>> ':10'
#>>> ':10:3'
#>>> '::3'

slice_repr((slice(None, None, 3), Ellipsis, 3))
#>>> '::3,...,3'

有很多特殊情况,这绝对不是固定的。然而,这是正确的。

这也不涉及Python 3上的X[[...]]这样的情况。这些很难做到,因为使用repr的任何容器都是“错误的”。对于您期望可能包含Ellipsis的每个对象,您必须使用特殊情况,这很痛苦。

同样的问题不适用于slice,因为它只能出现在__getitem__的顶层,因此X[[1:2]]不会发生。在Python 2上,...似乎也有这种限制。

答案 1 :(得分:-1)

没有更好的功能,但这个片段似乎很好地完成了所有的例子。

a = str(slice(1, 10)).replace('None, None','None').replace('slice(','').replace(', ',':').replace(')','').replace('None','')
if a.count(':') > 1 and a[len(a)-1] == ':': #Needed for cases like 1, 10, None
    a = a[:-1]