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

У меня есть список логических значений, где я иногда сбрасываю их все на false. После первой записи сброса как:

for b in bool_list:
    b = False

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

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

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

Это не совсем уж питонический язык. Что такого ценного в списке логических значений, что вы не можете его восстановить? Не могли бы вы подробнее рассказать об этом?

S.Lott 03.01.2009 23:22

В этом случае нет ничего, что мешало бы восстановить список.

Dan Homerick 03.01.2009 23:51
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
15
2
7 890
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

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

bool_list = [False] * len(bool_list)

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

См. Мой ответ на Очистить словарь Python для аналогичного примера.

Проголосовал против, потому что он указал, что ему нужно действовать в существующем списке.

Soviut 03.01.2009 23:15

Проголосовали, потому что «существующий список» можно легко заменить новым списком с помощью оператора присваивания.

S.Lott 03.01.2009 23:21

Также, если вы хотите изменить существующий список, вы можете изменить его на bool_list [:] = [False] * len (bool_list)

dF. 03.01.2009 23:28

Если это очень большой список, этот код может быть плохим, поскольку вы, по сути, делаете две копии списка. Но он должен работать примерно в 95% всех ситуаций.

Jason Baker 04.01.2009 02:34

Я бы не стал использовать диапазон и линзу. Намного чище использовать enumerate ()

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

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

Enumerate в этом случае кажется излишним. Вам даже не нужна переменная v, явный индикатор чрезмерной сложности. Простое понимание списка делает свою работу.

Algorias 04.01.2009 00:13

Чтобы выглядеть лучше, я бы все равно проголосовал за него. Заметной разницы в скорости нет. Фиктивная переменная того стоит. Думаю, дело в личном вкусе

Zoomulator 04.01.2009 00:55

неэффективен во всех требуемых отдельных элементах.

ironfroggy 04.01.2009 02:19

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

Первый пример будет «работать», только если вы не пытаетесь изменить элемент, содержащийся в списке. Если вы делаете для x в: x.foo (), тогда это, конечно, нормально. Однако, если a является списком dicts, то для x в a: x = {} не выполняет то, что предназначено, по той же причине, что и исходный вопрос.

Greg Hewgill 03.01.2009 23:25

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

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.

Зачем повторять предыдущий ответ? Почему бы не проголосовать за другой ответ? Я не уверен, что особенного в этом ответе. Возможно, я что-то упускаю. Не могли бы вы пересмотреть или расширить свой ответ, чтобы подчеркнуть уникальную информацию?

S.Lott 04.01.2009 02:08
Ответ принят как подходящий
bool_list[:] = [False] * len(bool_list)

или же

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

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

Dan Homerick 04.01.2009 21:47

Резюме С точки зрения производительности, 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 мксек на цикл

Я рад, что рассчитал их. До сих пор я думал, что умножение списков было аккуратным, но, вероятно, медленным.

Dan Homerick 04.01.2009 04:30

Хорошее резюме! Вы должны отметить это как ответ. Я понятия не имел, что numpy НАСТОЛЬКО быстрее. Черт возьми

Zoomulator 04.01.2009 12:22

Другие вопросы по теме