Изменить элементы списка - PullRequest
15 голосов
/ 03 января 2009

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

for b in bool_list:
    b = False

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

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

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

Ответы [ 8 ]

13 голосов
/ 03 января 2009

Вот еще одна версия:

bool_list = [False for item in bool_list]
13 голосов
/ 03 января 2009

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

bool_list = [False] * len(bool_list)

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

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

12 голосов
/ 04 января 2009

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

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

Оригинал:

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 мксек на петлю

11 голосов
/ 04 января 2009
bool_list[:] = [False] * len(bool_list)

или

bool_list[:] = [False for item in bool_list]
4 голосов
/ 03 января 2009

Если вы хотите использовать массивы 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
3 голосов
/ 03 января 2009

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

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

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

0 голосов
/ 04 января 2009

Я думаю

bool_list = [False for element in bool_list]

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

0 голосов
/ 03 января 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...