关于python:在不使用内置函数的情况下反转列表

Reverse a list without using built-in functions

我使用的是python 3.5。

作为问题的一部分,我试图设计一个将列表作为输入并还原它的函数。因此,如果x = [a, b, c],函数将使x = [c, b, a]

问题是,我不允许使用任何内置函数,这让我陷入困境。我最初的想法是在一个函数中执行以下循环:

1
2
for revert in range(1, len(x) + 1):
    y.append(x[-revert])

而且它是有效的。但问题是我使用的是len(x),我认为它是一个内置函数,对吗?

所以我四处搜索,并制作了以下非常简单的代码:

1
y = x[::-1]

这正是我想要的,但它似乎太简单/太简单,我不确定"::"是否算作一个函数。

所以我想知道是否有人对如何手动设计所说的函数有任何提示/想法?当你不能使用任何内置的功能时,这看起来真的很难,而且它让我陷入了相当长的一段时间。


rangelen都是内置功能。由于接受了list方法,您可以使用insert来实现这一点。它是reeaallyy slow*但是它不使用任何内置的小列表:

1
2
3
4
5
def rev(l):
    r = []
    for i in l:
        r.insert(0, i)
    return r

通过在第0个位置连续插入,您最终得到输入列表的反转版本:

1
2
>>> print(rev([1, 2, 3, 4]))
[4, 3, 2, 1]

做:

1
2
def rev(l):
    return l[::-1]

也可以被视为解决方案。::-1不是一个函数(它是一个切片),[]也是一个列表方法。而且,与insert相比,它更快,可读性更高;只需确保您能够理解和解释它。关于它如何工作的一个很好的解释可以在这个S.O答案中找到。

*Reeaallyyyy慢,见Juanpa.Arrivillaga对酷情节的回答和appendpop的回答,并像Yoav Glazner的回答中所做的那样,在列表中查看现有的reverse


另一种方法(只是为了完整性:)

1
2
3
4
def another_reverse(lst):
    new_lst = lst.copy() # make a copy if you don't want to ruin lst...
    new_lst.reverse() # notice! this will reverse it in place
    return new_lst


这里的解决方案不使用内置函数,而是依赖于列表方法。正如您的规范所暗示的那样,它倒过来了:

1
2
3
4
5
6
7
8
9
10
11
>>> x = [1,2,3,4]
>>> def reverse(seq):
...   temp = []
...   while seq:
...     temp.append(seq.pop())
...   seq[:] = temp
...
>>> reverse(x)
>>> x
[4, 3, 2, 1]
>>>

号埃塔

吉姆,你在0号位置用insert的回答让我发疯了!这个解是二次时间!您可以使用带有临时列表的appendpop来使用简单的列表方法实现线性时间。见(reverse为蓝色,rev为绿色):>。</P><P>如果使用<wyn>seq[:] = temp</wyn>有点像temp,并将每个项目附加到seq中,时间复杂度仍然是线性的,但可能较慢,因为它不使用基于C的内部结构。


::不是一个函数,它是一个python文本。以及[]

如何检查::, []是否正常工作。简单,

1
2
3
4
5
6
7
8
9
10
    import dis
    a = [1,2]
    dis.dis(compile('a[::-1]', '', 'eval'))
      1           0 LOAD_NAME                0 (a)
                  3 LOAD_CONST               0 (None)
                  6 LOAD_CONST               0 (None)
                  9 LOAD_CONST               2 (-1)
                 12 BUILD_SLICE              3
                 15 BINARY_SUBSCR
                 16 RETURN_VALUE

如果::,[]是函数,那么应该在a[::-1]语句执行的python指令中找到一个标签CALL_FUNCTION。所以,他们不是。

当你调用一个函数时,比如说list()函数,看看python指令是什么样子的。

1
2
3
4
>>> dis.dis(compile('list()', '', 'eval'))
  1           0 LOAD_NAME                0 (list)
              3 CALL_FUNCTION            0
              6 RETURN_VALUE

所以,基本上

1
2
def rev(f):
    return f[::-1]

工作正常。但是,如果你的问题是家庭作业或者是老师发的,我认为你应该做吉姆在回答中建议的事情。但是,你可以用最快的方式添加旁注。

如果你的老师抱怨[::-1]符号,给他看我给你的例子。


只需从右到左迭代列表即可获得项目。

1
2
3
4
5
6
7
8
9
10
a = [1,2,3,4]

def reverse_the_list(a):
   reversed_list = []
   for i in range(0, len(a)):
     reversed_list.append(a[len(a) - i - 1])
   return reversed_list

new_list = reverse_the_list(a)
print new_list


实现这一点的最有效的方法是通过列表切片。而且,由于您提到您不需要任何内置函数,所以它完全满足您的需求。例如:

1
2
3
4
5
>>> def reverse_list(list_obj):
...     return list_obj[::-1]
...
>>> reverse_list([1, 3, 5 , 3, 7])
[7, 3, 5, 3, 1]


完整性的另一种方法是,range()采用可选的step参数,允许您在列表中后退:

1
2
def reverse_list(l):
    return [l[i] for i in range(len(l)-1, -1, -1)]


您的示例:

1
y = x[::-1]

使用python slices表示法,在我假设您请求的意义上,它不是一个函数。从本质上说,::起到了分离器的作用。更详细的代码版本是:

1
y = x[len(x):None:-1]

1
y = x[start:end:step]

我可能不会抱怨Python让你的生活变得非常,非常容易。

编辑成超级书呆子。有人可能会说,调用[]根本就是使用一个内置的python函数,因为它实际上是方法__getitem__()的语法糖。

1
x.__getitem__(0) == x[0]

使用::确实利用了slice()对象。

1
x.__getitem__(slice(len(x), None, -1) == x[::-1]

但是…如果您要讨论这个问题,您在python中编写的任何内容都将使用内置的python函数。