编写类似reverse()函数的Python代码

时间:2015-04-13 02:49:48

标签: python list python-3.x reverse

我正在寻找打破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))

6 个答案:

答案 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])

你甚至不必自己递增indexfor循环处理它。


正如@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.appendnewlist[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()