Python: изменить элементы списка

У меня есть список булевых элементов, где иногда я reset все они относятся к false. После первого написания reset как:

for b in bool_list:
    b = False

Я нашел, что это не работает. Я провел минуту, царапая себе голову, затем вспомнил, что, конечно, это не сработает, так как я только изменяю ссылку на bool, а не его ценность. Поэтому я переписал как:

for i in xrange(len(bool_list)):
    bool_list[i] = False

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

Ответы

Ответ 1

bool_list[:] = [False] * len(bool_list)

или

bool_list[:] = [False for item in bool_list]

Ответ 2

Если у вас есть только одна ссылка на список, может быть проще:

bool_list = [False] * len(bool_list)

Это создает новый список, заполненный элементами False.

См. мой ответ на Python dictionary clear для аналогичного примера.

Ответ 3

Здесь другая версия:

bool_list = [False for item in bool_list]

Ответ 4

Резюме Производительность, количество или умножение списка являются явными победителями, поскольку они на 10-20 раз быстрее, чем другие подходы.

Я провел несколько тестов производительности по различным предложенным вариантам. Я использовал Python 2.5.2 на Linux (Ubuntu 8.10) с 1,5 ГГц Pentium M.

Оригинал:

python timeit.py -s 'bool_list = [True] * 1000' 'for x in xrange(len(bool_list)): bool_list[x] = False'

1000 циклов, лучший из 3: 280 usec за цикл

Репликация на основе Slice со списком:

python timeit.py -s 'bool_list = [True] * 1000' 'bool_list[:] = [False for element in bool_list]'

1000 циклов, лучше всего 3: 215 usec за цикл

Замена на основе среза с помощью генератора:

python timeit.py -s 'bool_list = [True] * 1000' 'bool_list[:] = (False for element in bool_list)'

1000 циклов, лучше всего 3: 265 usec за цикл

Перечислите

python timeit.py -s 'bool_list = [True] * 1000' 'for i, v in enumerate(bool_list): bool_list[i] = False'

1000 циклов, лучше всего 3: 385 мксек за цикл

Numpy

python timeit.py -s 'import numpy' -s 'bool_list = numpy.zeros((1000,), dtype=numpy.bool)' 'bool_list[:] = False'

10000 циклов, наилучший из 3: 15,9 usec за цикл

Репликация на основе Slice с умножением списка:

python timeit.py -s 'bool_list = [True] * 1000' 'bool_list[:] = [False] * len(bool_list)'

10000 циклов, лучше всего 3: 23,3 секунды за цикл

Справочная замена с умножением списка

 python timeit.py -s 'bool_list = [True] * 1000' 'bool_list = [False] * len(bool_list)'

10000 циклов, наилучший из 3: 11.3 usec за цикл

Ответ 5

Если вы захотите использовать numpy массивы, на самом деле очень легко сделать такие вещи, как использование срезов массива.

import numpy

bool_list = numpy.zeros((100,), dtype=numpy.bool)

# do something interesting with bool_list as if it were a normal list

bool_list[:] = False
# all elements have been reset to False now

Ответ 6

Я бы не использовал диапазон и len. Это намного чище использовать перечисление()

for i, v in enumerate(bool_list): #i, v = index and value
    bool_list[i] = False

В этом случае он остался с неиспользованной переменной, но по-прежнему выглядит более чистым. Там нет заметных изменений в производительности.

Ответ 7

Для типов значений, таких как int, bool и string, ваш второй пример примерно такой же, как и для его получения. Ваш первый пример будет работать с любыми ссылочными типами, такими как классы, dicts или другие списки.

Ответ 8

Я думаю,

bool_list = [False for element in bool_list]

является таким же питоническим, как и он. Использование списков, подобных этому, должно быть более быстрым, чем цикл for в python.