Я начинаю Python, и я пытаюсь использовать двумерный список, который я первоначально заполняю той же переменной в каждом месте. Я придумал это:
def initialize_twodlist(foo):
twod_list = []
new = []
for i in range (0, 10):
for j in range (0, 10):
new.append(foo)
twod_list.append(new)
new = []
Это дает желаемый результат, но чувствует себя подобно обходному решению. Существует ли более легкий/короче/больше изящный способ сделать это?
Часто встречающийся в Python паттерн
bar = []
for item in some_iterable:
bar.append(SOME EXPRESSION)
помог мотивировать введение list comprehensions, которые преобразуют этот фрагмент в
bar = [SOME EXPRESSION for item in some_iterable]
более короткий и иногда более понятный. Обычно у вас вырабатывается привычка распознавать их и часто заменять циклы на comprehensions.
Ваш код следует этому шаблону дважды
twod_list = [] \
for i in range (0, 10): \
new = [] \ can be replaced } this too
for j in range (0, 10): } with a list /
new.append(foo) / comprehension /
twod_list.append(new) /
Обычно, когда вам нужны многомерные массивы, вам нужен не список списков, а массив numpy или, возможно, dict.
Например, с помощью numpy вы должны сделать что-то вроде
import numpy
a = numpy.empty((10, 10))
a.fill(foo)
Этот способ быстрее , чем понимание вложенных списков
[x[:] for x in [[foo] * 10] * 10] # for immutable foo!
Вот некоторые тайминги python3 для малых и больших списков
$python3 -m timeit '[x[:] for x in [[1] * 10] * 10]'
1000000 loops, best of 3: 1.55 usec per loop
$ python3 -m timeit '[[1 for i in range(10)] for j in range(10)]'
100000 loops, best of 3: 6.44 usec per loop
$ python3 -m timeit '[x[:] for x in [[1] * 1000] * 1000]'
100 loops, best of 3: 5.5 msec per loop
$ python3 -m timeit '[[1 for i in range(1000)] for j in range(1000)]'
10 loops, best of 3: 27 msec per loop
Пояснение:
[[foo] * 10] * 10
создает список одного и того же объекта, повторяющийся 10 раз. Вы не можете просто использовать это, потому что изменение одного элемента изменит тот же элемент в каждой строке!
x [:]
эквивалентен list (X)
, но немного более эффективен, поскольку позволяет избежать поиска имени. В любом случае он создает мелкую копию каждой строки, поэтому теперь все элементы независимы.
Все элементы являются одним и тем же объектом foo
, поэтому, если foo
является изменяемым , вы не можете использовать эту схему., Вам придется использовать
import copy
[[copy.deepcopy(foo) for x in range(10)] for y in range(10)]
или предполагая класс (или функцию) Foo
, который возвращает foo
s
[[Foo() for x in range(10)] for y in range(10)]
Вы можете использовать понимание списка :
x = [[foo for i in range(10)] for j in range(10)]
# x is now a 10x10 array of 'foo' (which can depend on i and j if you want)