1) Почти английский стиль:
Проверьте наличие, используя in
оператор, затем примените remove
метод.
if thing in some_list: some_list.remove(thing)
remove
Метод будет удалить только первое вхождение thing
, чтобы удалить все вхождения , которые можно использовать while
вместо if
.
while thing in some_list: some_list.remove(thing)
- Достаточно просто, наверное, мой выбор. Для небольших списков (не выдерживает однострочников)
Такое отношение «стреляй первым - задавай вопросы - последнее» распространено в Python. Вместо того, чтобы заранее проверять, подходит ли объект, просто выполните операцию и поймайте соответствующие исключения:
try:
some_list.remove(thing)
except ValueError:
pass # or scream: thing not in some_list!
except AttributeError:
call_security("some_list not quacking like a list!")
Конечно, второе, за исключением пункта в вышеприведенном примере, имеет не только сомнительный юмор, но и совершенно ненужное (цель состояла в том, чтобы проиллюстрировать типизацию утки для людей, не знакомых с концепцией).
Если вы ожидаете многократного появления вещи:
while True:
try:
some_list.remove(thing)
except ValueError:
break
- немного многословно для этого конкретного случая использования, но очень идиоматично в Python.
- это работает лучше, чем # 1
- PEP 463 предложил более короткий синтаксис для try / кроме простого использования, который был бы здесь полезен, но не был одобрен.
Однако с помощью contextmanb contextlib's suppress () (представлен в python 3.4) приведенный выше код можно упростить до следующего:
with suppress(ValueError, AttributeError):
some_list.remove(thing)
Опять же, если вы ожидаете многократного появления вещи:
with suppress(ValueError):
while True:
some_list.remove(thing)
3) Функциональный стиль:
Около 1993, Python есть lambda
, reduce()
, filter()
и map()
, любезно Лисп хакера , который пропустил их и представили рабочие патчи *. Вы можете использовать filter
для удаления элементов из списка:
is_not_thing = lambda x: x is not thing
cleaned_list = filter(is_not_thing, some_list)
Существует ярлык, который может быть полезен для вашего случая: если вы хотите отфильтровать пустые элементы (фактически элементы, где bool(item) == False
, например None
, ноль, пустые строки или другие пустые коллекции), вы можете передать None в качестве первого аргумента:
cleaned_list = filter(None, some_list)
- [обновление] : в Python 2.x
filter(function, iterable)
раньше было эквивалентно [item for item in iterable if function(item)]
(или [item for item in iterable if item]
если первый аргумент None
); в Python 3.x он теперь эквивалентен (item for item in iterable if function(item))
. Тонкое отличие состоит в том, что фильтр, используемый для возврата списка, теперь работает как выражение генератора - это нормально, если вы перебираете только очищенный список и отбрасываете его, но если вам действительно нужен список, вы должны заключить filter()
вызов с list()
конструктором.
- * Эти ароматизированные конструкции Lispy считаются немного чужими в Python. Примерно в 2005 году Гвидо даже говорил об отбрасывании
filter
- вместе со своими компаньонами map
и reduce
(они еще не ушли, но reduce
были перенесены в модуль functools , который стоит посмотреть, если вам нравятся функции высокого порядка ).
4) Математический стиль:
Список постижения стали предпочтительным стилем для списка манипуляций в Python , так как введенные в версии 2.0 по PEP 202 . Обоснованием этого является , что описания списки обеспечивают более краткий способ создания списков в ситуациях , где map()
и filter()
будет в настоящее время используются и / или вложенные циклы.
cleaned_list = [ x for x in some_list if x is not thing ]
Выражения генератора были введены в версии 2.4 PEP 289 . Выражение генератора лучше для ситуаций, когда вам не нужно (или вы не хотите) иметь полный список, созданный в памяти - например, когда вы просто хотите перебирать элементы по одному. Если вы перебираете список, вы можете думать о выражении-генераторе как о ленивом вычислении списка:
for item in (x for x in some_list if x is not thing):
do_your_thing_with(item)
Ноты
- Вы можете использовать оператор неравенства
!=
вместо is not
( разница важна )
- для критиков методов, подразумевающих копию списка: вопреки распространенному мнению, выражения-генераторы не всегда более эффективны, чем списки - пожалуйста, запишите профиль, прежде чем жаловаться