Как инициализировать двухмерную антенную решетку в Python?

Я начинаю 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 = []

Это дает желаемый результат, но чувствует себя подобно обходному решению. Существует ли более легкий/короче/больше изящный способ сделать это?

241
задан Alex Martelli 7 March 2010 в 07:44
поделиться

5 ответов

Часто встречающийся в 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)                           /
361
ответ дан 23 November 2019 в 03:14
поделиться

Обычно, когда вам нужны многомерные массивы, вам нужен не список списков, а массив numpy или, возможно, dict.

Например, с помощью numpy вы должны сделать что-то вроде

import numpy
a = numpy.empty((10, 10))
a.fill(foo)
22
ответ дан 23 November 2019 в 03:14
поделиться
[[foo for x in xrange(10)] for y in xrange(10)]
25
ответ дан 23 November 2019 в 03:14
поделиться

Этот способ быстрее , чем понимание вложенных списков

[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)]
129
ответ дан 23 November 2019 в 03:14
поделиться

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

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)
205
ответ дан 23 November 2019 в 03:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: