У меня есть список логических значений, где я иногда сбрасываю их все на false. После первой записи сброса как:
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)
Это создает новый список, заполненный элементами False.
См. Мой ответ на Очистить словарь Python для аналогичного примера.
Проголосовал против, потому что он указал, что ему нужно действовать в существующем списке.
Проголосовали, потому что «существующий список» можно легко заменить новым списком с помощью оператора присваивания.
Также, если вы хотите изменить существующий список, вы можете изменить его на bool_list [:] = [False] * len (bool_list)
Если это очень большой список, этот код может быть плохим, поскольку вы, по сути, делаете две копии списка. Но он должен работать примерно в 95% всех ситуаций.
Я бы не стал использовать диапазон и линзу. Намного чище использовать enumerate ()
for i, v in enumerate(bool_list): #i, v = index and value
bool_list[i] = False
В этом случае остается неиспользованная переменная, но, на мой взгляд, она выглядит чище. Заметных изменений в производительности тоже нет.
Enumerate в этом случае кажется излишним. Вам даже не нужна переменная v, явный индикатор чрезмерной сложности. Простое понимание списка делает свою работу.
Чтобы выглядеть лучше, я бы все равно проголосовал за него. Заметной разницы в скорости нет. Фиктивная переменная того стоит. Думаю, дело в личном вкусе
неэффективен во всех требуемых отдельных элементах.
Для типов значений, таких как int, bool и string, ваш второй пример настолько хорош, насколько и будет. Ваш первый пример будет работать с любыми ссылочными типами, такими как классы, словари или другие списки.
Первый пример будет «работать», только если вы не пытаетесь изменить элемент, содержащийся в списке. Если вы делаете для x в: x.foo (), тогда это, конечно, нормально. Однако, если a является списком dicts, то для x в a: x = {} не выполняет то, что предназначено, по той же причине, что и исходный вопрос.
Если вы хотите использовать массивы тупой, на самом деле очень легко делать такие вещи, используя срезы массива.
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
Вот еще одна версия:
bool_list = [False for item in bool_list]
я думаю
bool_list = [False for element in bool_list]
настолько питонический, насколько это возможно. Использование подобных списков в целом должно быть быстрее, чем цикл for в Python.
Зачем повторять предыдущий ответ? Почему бы не проголосовать за другой ответ? Я не уверен, что особенного в этом ответе. Возможно, я что-то упускаю. Не могли бы вы пересмотреть или расширить свой ответ, чтобы подчеркнуть уникальную информацию?
bool_list[:] = [False] * len(bool_list)
или же
bool_list[:] = [False for item in bool_list]
Выбран, потому что эффект этого стиля ясен, не страдает ограничением, что есть только одна ссылка на список, а производительность для верхнего из них превосходна.
Резюме С точки зрения производительности, numpy или умножение списка - явные победители, поскольку они в 10-20 раз быстрее, чем другие подходы.
Я провел несколько тестов производительности различных предложенных вариантов. Я использовал Python 2.5.2 в Linux (Ubuntu 8.10) с Pentium M.
Оригинал:
python timeit.py -s 'bool_list = [True] * 1000' 'for x in xrange(len(bool_list)): bool_list[x] = False'
1000 петель, лучшее из 3: 280 мксек на петлю
Замена на основе срезов с пониманием списка:
python timeit.py -s 'bool_list = [True] * 1000' 'bool_list[:] = [False for element in bool_list]'
1000 циклов, лучшее из 3: 215 мксек на цикл
Замена на основе срезов с пониманием генератора:
python timeit.py -s 'bool_list = [True] * 1000' 'bool_list[:] = (False for element in bool_list)'
1000 циклов, лучшее из 3: 265 мксек на цикл
Перечислить:
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 мксек на цикл
Замена на основе срезов с умножением списка:
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 мксек на цикл
Я рад, что рассчитал их. До сих пор я думал, что умножение списков было аккуратным, но, вероятно, медленным.
Хорошее резюме! Вы должны отметить это как ответ. Я понятия не имел, что numpy НАСТОЛЬКО быстрее. Черт возьми
Это не совсем уж питонический язык. Что такого ценного в списке логических значений, что вы не можете его восстановить? Не могли бы вы подробнее рассказать об этом?