为什么此列表分配索引超出范围?

时间:2017-03-14 05:24:22

标签: python list append

我正在处理一个简单的左循环移位函数作为练习(即将其[1,2,3]提供并返回[[1,2,3],[2,3,1],[3,1,2]])。如果我使用这个版本的代码:

def left_shifts(L):
    if len(L) == 0:
        M = []
    elif len(L) == 1:
        M = deepcopy(L)
    else:
        M = [len(L)]
        M[0] = L
        for i in range(1,len(L)):
            M[i] = (L[i:] + L[:i])

    return M

print (left_shifts([1,2,3,4,5]))

我收到列表分配索引超出范围的错误。但是,如果我只是调整它:

def left_shifts(L):
    if len(L) == 0:
        M = []
    elif len(L) == 1:
        M = deepcopy(L)
    else:
        M = [len(L)]
        M[0] = L
        for i in range(1,len(L)):
            M.append((L[i:] + L[:i])) #changed line

    return M

print (left_shifts([1,2,3,4,5]))

工作正常。我的问题是:为什么上面的代码会产生这个错误?我所做的就是将两个列表一起添加并将其分配给另一个列表中的一个元素,我认为这是合法的。

2 个答案:

答案 0 :(得分:1)

M = [len(L)]使用一个元素创建一个列表,一个整数:

>>> L = [1, 2, 3]
>>> len(L)
3
>>> [len(L)]
[3]

这就是M[1]不存在的原因;你有一个长度为1的列表,所以只有索引0存在。

如果您希望创建包含len(L)元素的列表,则需要使用乘法:

M = [None] * len(L)

这会创建一个包含len(L) None引用的列表。但是,不要对可变对象使用列表乘法; [...] * N不会创建内容的副本;你得到N对相同内容的引用。当这些内容本身是可变的时,这很重要。

不是说你的代码需要这么复杂。只需使用列表理解:

def left_shifts(L):
    return [L[i:] + L[:i] for i in range(len(L))]

演示:

>>> def left_shifts(L):
...     return [L[i:] + L[:i] for i in range(len(L))]
...
>>> left_shifts([1, 2, 3])
[[1, 2, 3], [2, 3, 1], [3, 1, 2]]

答案 1 :(得分:1)

我认为解释此问题的最佳方法是稍微修改代码:

def left_shifts(L):
    if len(L) == 0:
        M = []
    elif len(L) == 1:
        M = deepcopy(L)
    else:
        M = [len(L)]
        print(M)
    return M

print (left_shifts([1,2,3,4,5]))

所以我改变它来打印你刚刚分配给M的东西。

输出:

[5]

你刚刚制作了一个数字为5的数组...... Python中的数组定义不会这样做。 Python使用独特的语法。另外,[]定义了一个列表,而不是一个数组。

只需使用追加功能。

新代码:

def left_shifts(L):
    if len(L) == 0:
        M = []
    elif len(L) == 1:
        M = deepcopy(L)
    else:
        M = []
        M.append(L)
        for i in range(1,len(L)):
            M.append((L[i:] + L[:i])) #changed line

    return M

print (left_shifts([1,2,3,4,5]))