[英]Why can't I slice a list with a tuple, when it seems to be supported by the Python grammar?
I've been learning Python for awhile using official Python site tutorial/library/reference.我一直在使用官方 Python 站点教程/库/参考来学习 Python 一段时间。 Today I just accidentally stumbled across formal slicing reference and can't figure out why nobody tells about one possible scenario that should work but unfortunately it doesn't.
今天我只是偶然偶然发现了正式的切片参考,并且无法弄清楚为什么没有人告诉一个可能的场景应该有效,但不幸的是它没有。
Namely, according tothis document it should be possible to select elements from the sequence using tuple of indexes and slices:也就是说,根据本文档,应该可以使用索引和切片的元组从序列中提取 select 元素:
lst = list(range(1, 100, 2))
slc = slice(10, 20, 3)
print( lst[ 1, 5, 8, slc, 30:40:5, 49 ] )
But as many of you might expect error pops-up但正如你们中的许多人可能期望的那样弹出错误
Traceback (most recent call last): File "./slice-test.py", line 68, in print( lst[ 1, 5, 8, slc, 30:40:5, 49 ] ) TypeError: list indices must be integers or slices, not tuple
回溯(最后一次调用):文件“./slice-test.py”,第 68 行,在 print(lst[ 1, 5, 8, slc, 30:40:5, 49 ] ) 类型错误:列表索引必须是整数或切片,而不是元组
This notation have been present in Python for a long time.这种符号在 Python 中已经存在很长时间了。 At least the same document for Python 2.x mentions this term as a "extended slicing"here
至少 Python 2.x 的相同文档在此处将此术语称为“扩展切片”
What am I missing here?我在这里想念什么? I probably misinterpret this notation but I can't figure out where is the catch(except the fact that this is not supported by interpreter of course).
我可能误解了这个符号,但我不知道问题在哪里(当然解释器不支持这一点除外)。
PS I've looked up for an answer elsewhere including this question . PS我已经在其他地方寻找答案,包括这个问题。
PPS This question is not about indexing or start:end:step slicing per se, so examples of these are not needed. PPS 这个问题与索引或 start:end:step 切片本身无关,因此不需要这些示例。
Namely, according to this document it should be possible to select elements from the sequence using tuple of indexes and slices
也就是说,根据本文档,应该可以使用索引和切片的元组从序列中提取 select 元素
The document tells you about what is syntactically valid Python code, that can be bytecode-compiled into a .pyc
file.该文档告诉您什么是语法上有效的 Python 代码,可以将其字节码编译成
.pyc
文件。 It does not tell you about what is semantically valid Python code, that will run without any errors.它没有告诉你什么是语义上有效的 Python 代码,它将运行没有任何错误。
Only SyntaxError
can be raised by syntactically invalid code.语法上无效的代码只能引发
SyntaxError
。 The language grammar only explains how to avoid those exceptions, not any others.语言语法仅解释如何避免这些异常,而不是任何其他异常。
It is allowed to use a tuple of indexes and slices to slice a Python object.允许使用索引和切片的元组来切片 Python object。 It is up to the object's type to define what happens as a result, or if an exception should occur instead.
由对象的类型来定义结果会发生什么,或者是否应该发生异常。
Python objects handle slicing (and subscription) using the magic method __getitem__
. Python 对象使用魔术方法
__getitem__
处理切片(和订阅)。 In older versions, this was only for subscription, and a separate __getslice__
would be used for slicing.在旧版本中,这仅用于订阅,并且单独的
__getslice__
将用于切片。 Either way, if there is only one item between the []
(ie, no commas in the code), it is passed directly - not as a 1-element tuple.无论哪种方式,如果
[]
之间只有一项(即代码中没有逗号),则直接传递它 - 而不是作为 1 元素元组。 (As explained there: everything that would be a valid subscription is also a valid slicing; these are read by the grammar as subscriptions instead of slicings.) Each slice - written using the special slice syntax, only valid in this slicing context - becomes a slice
object, which is passed to __getitem__
just like anything else. (正如那里所解释的:所有可能是有效订阅的东西也是有效的切片;这些被语法读取为订阅而不是切片。)每个切片 - 使用特殊切片语法编写,仅在此切片上下文中有效 - 成为
slice
object,就像其他任何东西一样传递给__getitem__
。
We can make our own class to test it:我们可以制作自己的 class 来测试它:
>>> class Tester:
... def __getitem__(self, x):
... return x
...
>>> t = Tester()
>>> t[0]
0
>>> t['test']
'test'
>>> t[1:2:3]
slice(1, 2, 3)
>>> t[::-1]
slice(None, None, -1)
>>> t[1,2]
(1, 2)
>>> t[(1,2)]
(1, 2)
>>> t[[1,2]]
[1, 2]
>>> t[::-1, ::-1]
(slice(None, None, -1), slice(None, None, -1))
>>> t[1, 5, 8, slice(10, 20, 3), 30:40:5, 49]
(1, 5, 8, slice(10, 20, 3), slice(30, 40, 5), 49)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.