【问题标题】:Minimal representation of a slice object切片对象的最小表示
【发布时间】:2014-11-20 01:29:07
【问题描述】:

是否有一种内置或简单的方法来表示切片对象,以便将表示放在括号内将导致相关的__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'

【问题讨论】:

  • 你打算用这样的字符串做什么?您不能将其作为参数传递给__getitem__;它不会解析这样一个字符串所需的值。 __getitem__ 长期以来一直支持直接接收切片对象作为参数:x.__getitem__(slice(10)) 等价于 x[:10]
  • 这实际上仅用于表示目的。

标签: python slice representation


【解决方案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 上,... 似乎也有这个限制。

【讨论】:

  • 谢谢!不是 X[[...]] 语法错误吗? (我猜至少是 2.7)
  • 奇怪; Python 3 有... 作为正确的语法,可在anywhere 使用。请注意我已经更新了我的代码几次,原来的答案是错误的。
  • “是的,type(X) is Y *是*正确的做法” - 为什么?如果我继承元组或切片怎么办?
  • @Eric 不能使用切片语法创建切片子类,因此不应该有解析为它的 repr
【解决方案2】:

没有做更好的功能,但这个 sn-p 这似乎很好地完成了你所有的例子。

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]

【讨论】:

    猜你喜欢
    • 2016-03-27
    • 2019-07-29
    • 2014-04-03
    • 2018-02-24
    • 2011-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-15
    相关资源
    最近更新 更多