9

Создать пустой список заданного размера в Python

3

Проблема с созданием и присвоением значений элементам списка в Python

Я пытаюсь создать пустой список, который может содержать 10 элементов. После этого я планирую присвоить значения элементам этого списка. Например, я использую следующий код:

xs = list()
for i in range(0, 9):
   xs[i] = i

Однако при выполнении этого кода возникает ошибка IndexError: list assignment index out of range.

Почему эта ошибка возникает, и как правильно создать список, чтобы присваивать значения его элементам?

5 ответ(ов)

13

Вы не можете присвоить значение элементу списка, используя синтаксис xs[i] = value, если список не инициализирован, как минимум, с i+1 элементами (так как первый индекс равен 0). Вместо этого используйте xs.append(value), чтобы добавлять элементы в конец списка. (Хотя вы могли бы использовать такой синтаксис, если бы работали со словарем вместо списка.)

Создание пустого списка:

>>> xs = [None] * 10
>>> xs
[None, None, None, None, None, None, None, None, None, None]

Присвоение значения существующему элементу списка:

>>> xs[1] = 5
>>> xs
[None, 5, None, None, None, None, None, None, None, None]

Имейте в виду, что попытка выполнить xs[15] = 5 вызовет ошибку, так как наш список содержит только 10 элементов.

Функция range(x) создает список чисел от [0, 1, 2, ... x-1].

# Только для версии 2.X. Используйте list(range(10)) в версии 3.X.
>>> xs = range(10)
>>> xs
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Использование функции для создания списка:

>>> def display():
...     xs = []
...     for i in range(9): # Это просто чтобы показать, как создать список.
...         xs.append(i)
...     return xs
... 
>>> print display()
[0, 1, 2, 3, 4, 5, 6, 7, 8]

Генерация списка (использованы квадраты чисел, потому что для range вам не нужно делать всего этого, вы можете просто вернуть range(0, 9)):

>>> def display():
...     return [x**2 for x in range(9)]
... 
>>> print display()
[0, 1, 4, 9, 16, 25, 36, 49, 64]
2

Попробуйте вместо этого:

lst = [None] * 10

Этот код создаст список размером 10, в котором каждое место инициализировано значением None. После этого вы можете добавлять элементы в него:

lst = [None] * 10
for i in range(10):
    lst[i] = i

Тем не менее, это не самый "питонический" способ делать вещи. Лучше сделать так:

lst = []
for i in range(10):
    lst.append(i)

Или даже проще, в Python 2.x вы можете сделать так, чтобы инициализировать список со значениями от 0 до 9:

lst = range(10)

А в Python 3.x:

lst = list(range(10))
1

Ваша проблема связана с тем, что когда вы создаете список списков в Python с помощью оператора умножения, как в примере a = [[]]*10, все элементы списка ссылаются на один и тот же объект. Это означает, что если вы измените один из вложенных списков, это изменение отразится на всех остальных, так как они указывают на один и тот же объект в памяти.

Пример, который вы привели:

>>> a = [[]]*10
>>> a[0].append(0)
>>> a
[[0], [0], [0], [0], [0], [0], [0], [0], [0], [0]]

Благодаря этому видим, что все 10 списков задействовали один и тот же вложенный список.

Чтобы избежать такой ситуации и создать независимые списки, можно использовать функцию, создающую новый объект для каждого элемента:

def init_list_of_objects(size):
    list_of_objects = []
    for i in range(size):
        list_of_objects.append([])  # создаем новый объект в каждой итерации
    return list_of_objects

>>> a = init_list_of_objects(10)
>>> a
[[], [], [], [], [], [], [], [], [], []]
>>> a[0].append(0)
>>> a
[[0], [], [], [], [], [], [], [], [], []]

Таким образом, каждый элемент списка a является отдельным объектом, что позволяет избежать проблем с ссылками.

Также, как вы отметили в редакции, существует более короткий и "питонистый" способ сделать то же самое с помощью генератора списков:

>>> a = [[] for _ in range(10)]

Это создает список из 10 отдельных списков, не связанных между собой, и проблема с общими ссылками больше не возникает.

Так что ваш подход с генератором списков — это действительно предпочтительный и более лаконичный способ создания списка списков в Python!

0

Меня удивляет, что никто не предложил этот простой способ создания списка из пустых списков. Хотя это старая тема, я добавлю это для полноты картины. Вот как можно создать список из 10 пустых списков:

x = [[] for i in range(10)]
0

Существует два «быстрых» способа создания списка:

x = длина_вашего_списка
a = [None] * x
# или
a = [None for _ in range(x)]

Похоже, что способ [None] * x работает быстрее:

>>> from timeit import timeit
>>> timeit("[None]*100", number=10000)
0.023542165756225586
>>> timeit("[None for _ in range(100)]", number=10000)
0.07616496086120605

Но если вас устраивает диапазон (например, [0,1,2,3,...,x-1]), тогда range(x) может быть самым быстрым решением:

>>> timeit("range(100)", number=10000)
0.012513160705566406

Таким образом, если вам нужен список, заполненный None, используйте [None] * x для повышения производительности. Если же вам нужен список с последовательными числами, range(x) будет лучшим выбором.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь