我正在寻找打破reverse()函数并在代码中写出来进行练习。我最终想出了如何做到这一点(通过原始列表后退并附加到新的'反向'列表),但想知道为什么这不起作用。
def reverse(list):
newlist = []
index = 0
while index < len(list):
newlist[index] = list[(len(list)) - 1 - index]
index = index + 1
return newlist
list = [1, 2, 3, 4, 5]
print(reverse(list))
答案 0 :(得分:4)
在Python中,如果索引的范围不在0和列表的长度之间,则无法访问/更新列表的元素。
在您的情况下,您尝试将元素分配给0,但列表为空。因此,它没有索引0.这就是它失败的原因,
IndexError:列表分配索引超出范围
相反,您可以使用append
功能,就像这样
newlist.append(list[(len(list)) - 1 - index])
除此之外,您可以使用range
功能向后计数
for index in range(len(list) - 1, -1, -1):
newlist.append(list[index])
你甚至不必自己递增index
,for
循环处理它。
正如@abarnert所建议的,您实际上可以迭代列表并在每次开头添加元素,如下所示
>>> def reverse(mylist):
... result = []
... for item in mylist:
... result.insert(0, item)
... return result
...
>>> reverse([1, 2, 3, 4, 5])
[5, 4, 3, 2, 1]
如果你想创建一个新的反向列表,你可能不必自己编写一个函数,而是可以使用slicing notation创建一个新的反向列表,就像这样
>>> mylist = [1, 2, 3, 4, 5]
>>> mylist[::-1]
[5, 4, 3, 2, 1]
但这并没有改变原始对象。
>>> mylist = [1, 2, 3, 4, 5]
>>> mylist[::-1]
[5, 4, 3, 2, 1]
>>> mylist
[1, 2, 3, 4, 5]
如果要更改原始对象,只需将切片指定回原始对象的切片,如下所示
>>> mylist
[1, 2, 3, 4, 5]
>>> mylist[:] = mylist[::-1]
>>> mylist
[5, 4, 3, 2, 1]
注意: reversed
实际上返回一个反向迭代器对象,而不是列表。因此,它并没有构建完整的列表。相反,当使用next
协议进行迭代时,它会逐个返回元素。
>>> reversed([1, 2, 3, 4, 5])
<list_reverseiterator object at 0x7fdc118ba978>
>>> for item in reversed([1, 2, 3, 4, 5]):
... print(item)
...
...
5
4
3
2
1
所以,您可能希望将其设为generator function,就像这样
>>> def reverse(mylist):
... for index in range(len(mylist) - 1, -1, -1):
... yield mylist[index]
...
...
>>> reverse([1, 2, 3, 4, 5])
<generator object reverse at 0x7fdc118f99d8>
因此reverse
函数返回一个生成器对象。如果您想要一个列表,那么您可以使用list
函数创建一个列表,如此
>>> list(reverse([1, 2, 3, 4, 5]))
[5, 4, 3, 2, 1]
如果您要逐个处理它,然后使用for
循环迭代它,就像这样
>>> for i in reverse([1, 2, 3, 4, 5]):
... print(i)
...
...
5
4
3
2
1
答案 1 :(得分:3)
首先不要覆盖内置问题(在您的情况下为list
)第二个newlist
的{{1}}为0,因此无法通过索引访问。
len
您可以创建一个列表,其中包含与输入列表相同长度的值,如此
def reverse(mylist):
newlist = [0] * len(mylist)
index = 0
while index < len(mylist):
newlist[index] = mylist[(len(mylist)) - 1 - index]
index = index + 1
return newlist
mylist = [1, 2, 3, 4, 5]
print(reverse(mylist))
答案 2 :(得分:1)
您无法为0长度列表分配任意索引。这样做会引发IndexError。由于您按顺序分配元素,因此您只需执行追加而不是对索引的赋值:
newlist.append(l[(len(l)) - 1 - index])
追加修改列表并自动增加其长度。
让原始代码工作的另一种方法是更改newlist
的初始化,以便它有足够的长度来支持索引操作:
newlist = [None for _ in range(len(l))]
我还要注意,在内置类型和函数之后命名并不是一个好主意。这样做会影响内置函数的功能。
答案 3 :(得分:1)
您需要使用list.append
。 newlist[0]
是一个有效的操作,如果列表中至少包含一个元素,但newlist
在第一次迭代中为空。此外,list
不是变量的好名称,因为有一个具有相同名称的python内置容器:
def reverse(lst):
newlist = []
index = 0
while index < len(lst):
newlist.append(lst[(len(list)) - 1 - index])
index += 1
return newlist
list = [1, 2, 3, 4, 5]
print(reverse(list))
答案 4 :(得分:1)
要编写您尝试撰写的功能,请参阅thefourtheye's answer。
但这不是reverse
的工作方式,也不是它的作用。它不是创建新列表,而是就地修改现有列表。
如果你考虑一下,那很简单:只需要通过一半的指数,对于每个指数N,从左边交换第N个,从右边交换第N个。*
所以,坚持使用现有的框架:
def reverse(lst):
index = 0
while index < len(lst)/2:
lst[index], lst[len(lst) - 1 - index] = lst[len(lst) - 1 - index], lst[index]
index = index + 1
作为旁注,像这样使用while
循环几乎总是一个坏主意。如果您想循环一系列数字,只需使用for index in range(len(lst)):
即可。除了将三行代码减少到一行并使其更加明显你正在做什么之外,它还会删除多个地方,你可以做出一个简单而又痛苦的调试错误。
另外,请注意,在大多数情况下,在Python中,使用负索引更容易从右边缘使用#34;&#34;而不是自己做数学,而且它通常会删除一个可能容易犯一个痛苦错误的地方。但在这种特殊情况下,实际上可能不会出现任何错误......
*你必须确保你仔细考虑边缘情况。对于奇数列表你是否将中间元素与自身交换起来并不重要,但只是确保你没有绕错路并且将一个元素放得太远或太短。这是一个学习如何编写好的单元测试的好机会......
答案 5 :(得分:0)
可能会检查出来:
def reverse(lst):
newList = []
countList = len(lst) - 1
for x in range(countList,-1,-1):
newList.append(lst[x])
return newList
def main():
lst = [9,8,7,6,5,4,2]
print(reverse(lst))
main()