是否存在将同一个列表切片两次更好的情况?



情况如下:我有一个简单的列表

my_list = list(range(10))  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

我可以对它执行两个切片,并打印结果如下:

print(my_list[9:1:-1][::-1]) # [2, 3, 4, 5, 6, 7, 8, 9]

但这当然可以用单个切片完成:

print(my_list[2:]) # [2, 3, 4, 5, 6, 7, 8, 9]

是否有一个很好的理由去做我在第二行代码中所展示的事情,即对同一个列表进行两次切片?这看起来非常不python,但也许有一个用例,切片参数是由变量提供的。为什么存在像我上面所做的那样对同一个列表进行双重切片的功能?

我想不出一个"好的理由";要切片两次,但想要推回"为什么存在对同一列表进行双重切片的功能…?"因为你的不是对同一个列表切片两次。初始的my_list[9:1:-1]创建一个全新的列表,然后[::-1]这个列表进行切片。该语言根本没有做任何事情来迎合这一点:[::-1]适用于任何可切片的对象,而my_list[9:1:-1]只是创建可切片对象的许多方法之一。

所以你的问题类似于问"为什么存在对同一个整数加两次的功能?"关于代码i = j + 5 + 8。: -)

一个例子这在某种程度上是人为的,但如果它在现实生活中出现在非时间临界部分,我会毫不犹豫地使用双切片。

假设您想要获得序列中每一个第98个元素,但也要以相反的顺序。所以,例如,

>>> xs = list(range(1000))
>>> xs[::98][::-1]
[980, 882, 784, 686, 588, 490, 392, 294, 196, 98, 0]

这个可以用一个切片得到,但我敢打赌大多数人会努力拼写正确:

>>> xs[980::-98]
[980, 882, 784, 686, 588, 490, 392, 294, 196, 98, 0]
>>>

请注意,您必须自己计算980,否则您将不知道反转切片应该从哪里开始。并且必须省略第二个slice参数(或者在那里显式地使用None)。

0不工作,因为切片在到达第二个索引之前停止:

>>> xs[980:0:-98]
[980, 882, 784, 686, 588, 490, 392, 294, 196, 98]

请注意,后面的0丢失了。-1也不行,尽管

>>> list(range(980, -1, -98))
[980, 882, 784, 686, 588, 490, 392, 294, 196, 98, 0]

工作好。但那是range()。在切片上下文中,-1表示"序列的最后一个元素",而不是第一个元素。

>>> xs[980:-1:-98]
[]

从元素980返回到元素999,当然会得到一个空列表。

在一般情况下获得正确的反向切片是非常棘手的。

我以前遇到过这样的问题,我想从一个端点依赖于用户输入的列表中获得一个反向切片。那么,一个简单的例子:

start = int(input('low index for slice (inclusive): '))
end = int(input('high index for slice (inclusive): '))
my_slice = original[end:start-1:-1]

哎呀:当为start提供0时,索引变成了-1,这导致它不能按预期工作。我们可以对这种情况进行特殊处理,用None代替-1;但是"特殊情况"还不足以打破规则,而且"简单比复杂好"。直接写original[start:end+1][::-1]要好得多,也更容易理解。

当你这样做的时候-

print(my_list[9:1:-1][::-1]) # [2, 3, 4, 5, 6, 7, 8, 9]

然后你首先创建一个新列表my_list[9:1:-1],然后你通过创建另一个新列表my_list[9:1:-1][::-1]来分割这个新列表。这将占用更多的空间。

但是当你这样做时-

print(my_list[2:]) # [2, 3, 4, 5, 6, 7, 8, 9]

你只创建一个新列表一次,这占用更少的空间

相关内容