Ответ 1
bool_list[:] = [False] * len(bool_list)
или
bool_list[:] = [False for item in bool_list]
У меня есть список булевых элементов, где иногда я reset все они относятся к false. После первого написания reset как:
for b in bool_list:
b = False
Я нашел, что это не работает. Я провел минуту, царапая себе голову, затем вспомнил, что, конечно, это не сработает, так как я только изменяю ссылку на bool, а не его ценность. Поэтому я переписал как:
for i in xrange(len(bool_list)):
bool_list[i] = False
и все работает отлично. Но я обнаружил, что спрашиваю: "Это действительно самый пифонический способ изменить все элементы списка?" Существуют ли другие способы, которые могут быть более эффективными или более ясными?
bool_list[:] = [False] * len(bool_list)
или
bool_list[:] = [False for item in bool_list]
Если у вас есть только одна ссылка на список, может быть проще:
bool_list = [False] * len(bool_list)
Это создает новый список, заполненный элементами False
.
См. мой ответ на Python dictionary clear для аналогичного примера.
Здесь другая версия:
bool_list = [False for item in bool_list]
Резюме Производительность, количество или умножение списка являются явными победителями, поскольку они на 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 за цикл
Если вы захотите использовать 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
Я бы не использовал диапазон и len. Это намного чище использовать перечисление()
for i, v in enumerate(bool_list): #i, v = index and value
bool_list[i] = False
В этом случае он остался с неиспользованной переменной, но по-прежнему выглядит более чистым. Там нет заметных изменений в производительности.
Для типов значений, таких как int, bool и string, ваш второй пример примерно такой же, как и для его получения. Ваш первый пример будет работать с любыми ссылочными типами, такими как классы, dicts или другие списки.
Я думаю,
bool_list = [False for element in bool_list]
является таким же питоническим, как и он. Использование списков, подобных этому, должно быть более быстрым, чем цикл for в python.