Я хочу создать серию списков различной длины. Каждый список будет содержать один и тот же элемент e
, повторяющийся n
раз (где n
= длина списка).
Как мне создать списки, не используя списки [e for number in xrange(n)]
для каждого списка?
Я хочу создать серию списков различной длины. Каждый список будет содержать один и тот же элемент e
, повторяющийся n
раз (где n
= длина списка).
Как мне создать списки, не используя списки [e for number in xrange(n)]
для каждого списка?
Ответы:
Вы также можете написать:
[e] * n
Вы должны заметить, что если e является, например, пустым списком, вы получите список с n ссылками на один и тот же список, а не с n независимыми пустыми списками.
Тестирование производительности
На первый взгляд кажется, что repeat - самый быстрый способ создать список с 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
.
[[]] * n
может привести к неожиданным результатам. Чтобы создать уникальные пустые [[] for i in range(0,n)]
Создать список одного элемента, повторяется n раз в Python
Для неизменяемых элементов, таких как None, bools, ints, float, string, кортежи или frozensets, вы можете сделать это следующим образом:
[e] * 4
Обратите внимание, что это лучше всего использовать только с неизменяемыми элементами (строками, кортежами, frozensets,) в списке, потому что все они указывают на один и тот же элемент в одном и том же месте в памяти. Я использую это часто, когда мне нужно построить таблицу со схемой из всех строк, чтобы мне не приходилось давать сильно избыточное сопоставление один к одному.
schema = ['string'] * len(columns)
Я уже давно использую Python, и никогда не видел ни одного варианта использования, где бы я делал это с изменяемым экземпляром. Вместо этого, чтобы получить, скажем, изменчивый пустой список, набор или dict, вы должны сделать что-то вроде этого:
list_of_lists = [[] for _ in columns]
Подчеркивание - это просто одноразовое имя переменной в этом контексте.
Если у вас есть только номер, это будет:
list_of_lists = [[] for _ in range(4)]
Это на _
самом деле не особенное, но ваша программа проверки стиля среды кодирования, вероятно, пожалуется, если вы не собираетесь использовать переменную и использовать любое другое имя.
Остерегайтесь делать это с изменяемыми объектами , когда вы меняете один из них, они все меняются, потому что они все один и тот же объект
foo = [[]] * 4
foo[0].append('x')
Foo теперь возвращает:
[['x'], ['x'], ['x'], ['x']]
Но с неизменяемыми объектами вы можете заставить его работать, потому что вы изменяете ссылку, а не объект:
>>> l = [0] * 4
>>> l[0] += 1
>>> l
[1, 0, 0, 0]
>>> l = [frozenset()] * 4
>>> l[0] |= set('abc')
>>> l
[frozenset(['a', 'c', 'b']), frozenset([]), frozenset([]), frozenset([])]
Но опять же, изменяемые объекты не годятся для этого, потому что операции на месте изменяют объект, а не ссылку:
l = [set()] * 4
>>> l[0] |= set('abc')
>>> l
[set(['a', 'c', 'b']), set(['a', 'c', 'b']), set(['a', 'c', 'b']), set(['a', 'c', 'b'])]
Itertools имеет функцию только для этого:
import itertools
it = itertools.repeat(e,n)
Конечно, itertools
вы получите итератор вместо списка. [e] * n
дает вам список, но, в зависимости от того, что вы будете делать с этими последовательностями, itertools
вариант может быть гораздо более эффективным.
Как уже отмечали другие, использование оператора * для изменяемого объекта дублирует ссылки, поэтому, если вы измените один, вы измените их все. Если вы хотите создать независимые экземпляры изменяемого объекта, ваш синтаксис xrange - самый питонский способ сделать это. Если вас беспокоит наличие именованной переменной, которая никогда не используется, вы можете использовать анонимную переменную подчеркивания.
[e for _ in xrange(n)]
[e] * n
должно сработать