Создать список одного элемента, повторяющегося n раз в Python


Я знаю, что понимание списка сделает это, но мне было интересно, есть ли еще более короткий (и более Питонический?) подход.

Я хочу создать серию списков, все разной длины. Каждый список будет содержать один и тот же элемент e, повторенный n раз (где n = длина списка). Как мне создать списки, не делая

[e for number in xrange(n)]

для каждого списка?

6 351

6 ответов:

вы также можете написать:

[e] * n

вы должны отметить, что если e, например, пустой список, вы получаете список с n ссылками на тот же список, а не N независимых пустых списков.

тестирование производительности

на первый взгляд кажется этот повтор-самый быстрый способ создать список из n одинаковых элементов:

>>> timeit.timeit('itertools.repeat(0, 10)', 'import itertools', number = 1000000)
0.37095273281943264
>>> timeit.timeit('[0] * 10', 'import itertools', number = 1000000)
0.5577236771712819

но подождите-это нечестный тест...

>>> itertools.repeat(0, 10)
repeat(0, 10)  # Not a list!!!

функции itertools.repeat на самом деле не создать список, он просто создает объект, который может быть использован для создания списка, если вы хотите! Давайте попробуем еще раз, но преобразование в список:

>>> timeit.timeit('list(itertools.repeat(0, 10))', 'import itertools', number = 1000000)
1.7508119747063233

так что если вы хотите список, используйте [e] * n. Если вы хотите создать элементы лениво, используйте repeat.

>>> [5] * 4
[5, 5, 5, 5]

будьте осторожны, когда повторяемый элемент является списком. Список не будет клонирован: все элементы будут ссылаться на один и тот же список!

>>> x=[5]
>>> y=[x] * 4
>>> y
[[5], [5], [5], [5]]
>>> y[0][0] = 6
>>> y
[[6], [6], [6], [6]]

создать список одного элемента повторяется n раз в Python

неизменяемые элементы

для неизменяемых элементов, таких как None, strings, tuples или frozensets, вы можете сделать это следующим образом:

[e] * 4

обратите внимание, что это лучше всего использовать только с неизменяемыми элементами (строки, кортежи, frozensets,) в списке, потому что все они указывают на один и тот же элемент в том же месте в памяти. Я часто использую это, когда мне нужно построить таблицу со схемой всех строки, так что мне не нужно давать сопоставление один к одному.

schema = ['string'] * len(columns)

изменяемые элементы

Я уже давно использую Python, и я никогда не видел прецедента, где я бы сделал это с изменяемым экземпляром. Вместо этого, чтобы получить, скажем, изменяемый пустой список, набор или дикт, вы должны сделать что-то вроде этого:

list_of_lists = [[] for _ in columns]

подчеркивание-это просто одноразовое имя переменной в этом контексте.

если у вас есть только номер, что бы быть:

list_of_lists = [[] for _ in range(4)]

The _ на самом деле не является особенным, но ваша проверка стиля среды кодирования, вероятно, будет жаловаться, если вы не собираетесь использовать переменную и использовать любое другое имя.


предостережения для использования неизменяемого метода с изменяемыми элементами:

остерегайтесь делать это с изменяемыми объектами, когда вы меняете один из них, они все меняются, потому что они все то же самое

Itertools имеет функцию только для этого:

import itertools
it = itertools.repeat(e,n)

конечно itertools дает итератор, а не список. [e] * n дает список, но, в зависимости от того, что вы будете делать с теми последовательностей itertools вариант может быть гораздо более эффективным.

как указывали другие, использование оператора * для изменяемого объекта дублирует ссылки, поэтому, если вы измените один, вы измените их все. Если вы хотите создать независимые экземпляры изменяемого объекта, ваш синтаксис xrange-это самый Питонический способ сделать это. Если вас беспокоит наличие именованной переменной, которая никогда не используется, Вы можете использовать анонимную переменную подчеркивания.

[e for _ in xrange(n)]
[e] * n

должно работать