Python表达式文档中的“Slicing”

27

我不理解Python文档中以下部分:

http://docs.python.org/reference/expressions.html#slicings

这是在讨论列表切片(x=[1,2,3,4]; x[0:2])吗?特别是与省略号有关的部分。

slice_item       ::=  expression | proper_slice | ellipsis

切片项为表达式时,其转换结果即为该表达式。省略号切片项的转换结果为内置的Ellipsis对象。
3个回答

34

省略号主要被NumPy扩展库使用,该库添加了一种多维数组类型。由于有多个维度,切片比只有起始和结束索引更复杂;能够在多个维度上对切片进行切割是很有用的。例如,给定一个4x4的数组,左上角区域将由切片“[:2,:2]”定义。

>>> a
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12],
       [13, 14, 15, 16]])

>>> a[:2,:2]  # top left
array([[1, 2],
       [5, 6]])

这里使用省略号表示数组中未指定的其余维度的占位符。可以将其视为表示未指定维度的完整切片 [:],因此对于3D数组,a[...,0]a[:,:,0]相同,对于4D,则为a[:,:,:,0]

请注意,在python2中,实际的省略号(...)文本只能在切片语法中使用,但有一个内置的省略号对象。这就是所谓的“省略符切片项的转换是内置的省略符对象”。即 "a[...]"实际上是"a[Ellipsis]"的简写。 在python3中,...表示任何地方的省略符,因此您可以编写:

>>> ...
Ellipsis

如果您没有使用numpy,那么您基本上可以忽略所有关于省略号的提及。因为内置类型都没有使用它,所以你只需要关心列表被传递一个包含"start", "stop"和"step"成员的单个切片对象即可,例如:

l[start:stop:step]   # proper_slice syntax from the docs you quote.

等同于调用:

l.__getitem__(slice(start, stop, step))

1
“请注意,实际的省略号文字(...)在Python2中无法在切片语法之外使用”这个说法并不完全准确。您可以按照以下方式使用“...”。假设a是定义了__getitem__(self, key)的类实例,则可以使用a[3,...,5]。正确的说法应该是,在索引查找运算符之外,无法使用省略号。 - Ankur Agarwal
1
@abc:a[3, ..., 5] 技术上是切片语法。 - user2357112
2
@user2357112支持Monica,我在Python2和Python3中尝试了a = [0,1,2,3,4,5,6,7]; print(a[3, ..., 5]),但两次都得到了TypeError: list indices must be integers, not tuple的错误提示。 - joseville

27

定义一个简单的测试类,只打印传递过来的内容:

>>> class TestGetitem(object):
...   def __getitem__(self, item):
...     print type(item), item
... 
>>> t = TestGetitem()

表达式示例:
>>> t[1]
<type 'int'> 1
>>> t[3-2]
<type 'int'> 1
>>> t['test']
<type 'str'> test
>>> t[t]
<class '__main__.TestGetitem'> <__main__.TestGetitem object at 0xb7e9bc4c>

切片示例:

>>> t[1:2]
<type 'slice'> slice(1, 2, None)
>>> t[1:'this':t]
<type 'slice'> slice(1, 'this', <__main__.TestGetitem object at 0xb7e9bc4c>)

省略号示例:

>>> t[...]
<type 'ellipsis'> Ellipsis

带省略号和切片的元组:

>>> t[...,1:]
<type 'tuple'> (Ellipsis, slice(1, None, None))

10

下面是发生的事情。请参见http://docs.python.org/reference/datamodel.html#typeshttp://docs.python.org/library/functions.html#slice

使用扩展片段语法时,切片对象用于表示切片。这是使用两个冒号(:)的切片,或由逗号分隔的多个切片或省略号(...),例如,a[i:j:step],a[i:j, k:l]或a[..., i:j]。它们也可以通过内置函数slice()创建。

特殊只读属性:start是下限;stop是上限;step是步长值;如果省略,则每个属性都为None。这些属性可以具有任何类型。

x=[1,2,3,4]
x[0:2]

"0:2" 被转换成一个 Slice 对象,起始位置为0,终止位置为2,步长为None。

你定义的类的 __getitem__ 方法将接收到这个 Slice对象。

>>> class MyClass( object ):
    def __getitem__( self, key ):
        print type(key), key


>>> x=MyClass()
>>> x[0:2]
<type 'slice'> slice(0, 2, None)

但是对于内置列表类,必须覆盖特殊的__getslice__方法。

class MyList( list ):
    def __getslice__( self, i, j=None, k=None ):
        # decode various parts of the slice values

省略号是一种特殊的“忽略此维度”的语法,可用于多维切片。

还请参阅http://docs.python.org/library/itertools.html#itertools.islice以获取更多信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接