Сценарий тестирования для различных методов, предложенных в ответах на этот вопрос: gist.github.com/zigg/6280653
zigg
Ответы:
2845
Чтобы удалить ключ независимо от того, находится ли он в словаре, используйте форму с двумя аргументами dict.pop():
my_dict.pop('key',None)
Это вернется, my_dict[key]если keyсуществует в словаре, иNone противном случае. Если второй параметр не указан (т. Е. my_dict.pop('key')) И keyне существует, значение KeyErrorповышается.
Чтобы удалить ключ, который гарантированно существует, вы также можете использовать
Иногда преимущество использования pop()over del: он возвращает значение для этого ключа. Таким образом, вы можете получить и удалить запись из dict в одной строке кода.
Кратенко
7
В вопросе не требуется сохранять значение. Это только добавит ненужную сложность. Ответ от @zigg (ниже) намного лучше.
Сальваторе
10
@SalvatoreCosentino Я не могу следовать твоим аргументам. Как код в этом ответе является более сложным, чем код в другом ответе?
Свен Марнач
33
@SalvatoreCosentino Нет, игнорирование возвращаемого значения функции вовсе не является неэффективным. Скорее наоборот - это решение намного быстрее, чем try/ exceptрешение, если ключ не существует. Возможно, вам будет легче читать одну или другую, и это нормально. Оба идиоматических Python, так что выбирайте все, что вы предпочитаете. Но утверждать, что этот ответ является более сложным или неэффективным, просто не имеет смысла.
Свен Марнах
5
@ user5359531 Я не понимаю. Как это проблема? Ни один из методов встроенных типов Python не вернется self, поэтому было бы довольно удивительно, если бы это сделал.
Свен Марнах
353
В частности, чтобы ответить "есть ли способ сделать это в одну строку?"
if'key'in my_dict:del my_dict['key']
... хорошо, вы спросили ;-)
Однако вы должны учитывать, что этот способ удаления объекта из a неdict является атомарным - возможно, что он 'key'может присутствовать my_dictво время ifоператора, но может быть удален до delего выполнения, и в этом случае delпроизойдет сбой с помощью a KeyError. Учитывая это, было бы безопаснее использоватьdict.pop или что-то вроде
try:del my_dict['key']exceptKeyError:pass
что, конечно, определенно не является одной строкой.
Да, popэто определенно более лаконично, хотя есть одно ключевое преимущество в этом: сразу понятно, что он делает.
zigg
4
try/exceptУтверждение является более дорогим. Вызывать исключение медленно.
Крис Баркер
16
@ChrisBarker Я обнаружил, что если ключ существует, то tryон немного быстрее, хотя, если нет, tryдействительно намного медленнее. popявляется достаточно последовательным, но медленнее, чем все, но tryс отсутствующим ключом. См. Gist.github.com/zigg/6280653 . В конечном счете, это зависит от того, как часто вы ожидаете, что ключ действительно будет в словаре, и от того, нужна ли вам атомарность, и, конечно же, от того, занимаетесь ли вы преждевременной оптимизацией;)
zigg
9
Я считаю, что значение ясности не следует упускать из виду. +1 за это.
Хуан Карлос Кото
2
Что касается расходов попробовать / кроме, вы также можете пойти if 'key' in mydict: #then del.... Мне нужно было извлечь ключ / val из dict для правильного разбора, pop не был идеальным решением.
Марк
153
Мне потребовалось некоторое время, чтобы понять, что именно my_dict.pop("key", None)делает. Поэтому я добавлю это в качестве ответа, чтобы сэкономить время для других Google:
pop(key[, default])
Если ключ находится в словаре, удалите его и верните его значение, иначе верните значение по умолчанию . Если значение по умолчанию не задано, а ключ отсутствует в словаре, a KeyErrorповышается.
Просто введите help (dict.pop) в интерпретаторе python.
Дэвид Малдер
13
help () и dir () могут быть вашими друзьями, когда вам нужно знать, что что-то делает.
Дэвид Малдер
3
или dict.pop?в IPython.
Эрик Каплун
51
del my_dict[key]немного быстрее, чем my_dict.pop(key)для удаления ключа из словаря, когда ключ существует
>>>import timeit
>>> setup ="d = {i: i for i in range(100000)}">>> timeit.timeit("del d[3]", setup=setup, number=1)1.79e-06>>> timeit.timeit("d.pop(3)", setup=setup, number=1)2.09e-06>>> timeit.timeit("d2 = {key: val for key, val in d.items() if key != 3}", setup=setup, number=1)0.00786
Но когда ключ не существует, if key in my_dict: del my_dict[key]это немного быстрее, чем my_dict.pop(key, None). Оба по крайней мере в три раза быстрее, чем delв try/ exceptоператор:
Измерять время такой быстрой операции довольно глупо. Ваш код, вероятно, не станет намного быстрее, потому что вы изменили popна a del. Создание словаря полностью превзойдёт его удаление.
Борис
1
@Boris - это полезное упражнение.
маргаритка
1
@daisy , что я говорю, что вы должны выбрать наиболее читаемый синтаксис не операцию , которая находится в 300 наносекунд быстрее (что буквально разница между delи popиз первого набора таймингов выше)
Борис
Кроме того, эти операции настолько быстры, что эти сроки не являются надежными.
Борис
46
Если вам нужно удалить много ключей из словаря в одной строке кода, я думаю, что использование map () довольно лаконично и читабельно на Pythonic:
myDict ={'a':1,'b':2,'c':3,'d':4}
map(myDict.pop,['a','c'])# The list of keys to remove>>> myDict
{'b':2,'d':4}
И если вам нужно отлавливать ошибки, когда вы выводите значение, которого нет в словаре, используйте lambda в map () следующим образом:
map(lambda x: myDict.pop(x,None),['a','c','e'])[1,3,None]# pop returns>>> myDict
{'b':2,'d':4}
или python3, вместо этого, вы должны использовать понимание списка:
[myDict.pop(x,None)for x in['a','c','e']]
Оно работает. И «e» не вызывало ошибку, даже если у myDict не было клавиши «e».
Это не будет работать в Python 3, потому что mapтеперь друзья ленивы и возвращают итераторы. Использование mapдля побочных эффектов обычно считается плохой практикой; стандартный for ... inцикл будет лучше. Посмотрите Представления И Итераторы вместо Списков для получения дополнительной информации.
Грег Кример
5
Независимо от вкуса и стиля практики, списки должны работать в Py3 [myDict.pop(i, None) for i in ['a', 'c']], поскольку они предлагают общую альтернативу map(и filter).
Майкл
@MichaelEkoka Вы не должны использовать списочные выражения для их побочных эффектов, используйте обычный for ... inцикл.
Борис
@ Борис Ты, наверное, прав. Мой ответ конкретно касается использования map(), которое часто используется для его побочных эффектов. Рекомендованной альтернативой в Python является понимание списка, которое, на мой взгляд, все еще вполне читабельно и когнитивно легко, как однострочный (см. Вопрос). Используемые только для побочных эффектов, обе конструкции действительно приводят к бесполезному списку, который может быть неэффективным. Начиная с Python3, я не знаю встроенной функции, которая может безопасно и элегантно выполнять итерацию по выражению генератора, без дорогостоящего побочного продукта, например loop(d.pop(k) for k in ['a', 'b']).
Майкл Экока
Меня удивляет, что мой самый голосующий за все время ответ включает в себя некоторые хаки, которые я бы никогда не использовал. Понимание списка (вариант 3) - наименее плохой подход, по моему мнению. Используйте это.
Марк Максмейстер
20
Вы можете использовать словарное понимание, чтобы создать новый словарь с удаленным этим ключом:
>>> my_dict ={k: v for k, v in my_dict.items()if k !='key'}
Вы можете удалить по условиям. Нет ошибки, если keyне существует.
Но следует помнить, что в этом процессе он фактически не удалит какой-либо ключ из словаря, а не исключит конкретный ключ из этого словаря. Кроме того, я заметил, что он вернул словарь, который не был упорядочен так же, как myDict.
myDict ={'one':100,'two':200,'three':300,'four':400,'five':500}{key:value for key, value in myDict.items()if key !='one'}
Если мы запустим его в оболочке, он выполнит что-то вроде {'five': 500, 'four': 400, 'three': 300, 'two': 200}- обратите внимание, что это не тот же порядок, что и myDict. Опять же, если мы попытаемся напечатать myDict, то увидим все ключи, включая которые мы исключили из словаря этим подходом. Однако мы можем создать новый словарь, назначив следующую переменную в переменную:
var ={key:value for key, value in myDict.items()if key !='one'}
Теперь, если мы попытаемся распечатать его, он будет следовать родительскому порядку:
Не используйте, if myDict.get('one')чтобы проверить, присутствует ли ключ! Сбой, если myDict ['one'] имеет значение false. Кроме того, у дикторов нет внутреннего порядка, поэтому нет смысла упоминать об этом.
Роб
Диск @Rob упорядочен по порядку вставки, начиная с CPython 3.6 и всех других реализаций Python, начиная с 3.7.
Борис
4
Вы можете использовать обработку исключений, если хотите быть очень многословным:
try:del dict[key]exceptKeyError:pass
Однако это медленнее, чем pop()метод, если ключ не существует.
my_dict.pop('key',None)
Для нескольких клавиш это не имеет значения, но если вы делаете это неоднократно, тогда лучше использовать последний метод.
Самый быстрый подход заключается в следующем:
if'key'in dict:del myDict['key']
Но этот метод опасен, потому что если он 'key'будет удален между двумя строками, KeyErrorбудет поднят.
items () в сочетании с пониманием dict может также помочь нам решить задачу удаления пары ключ-значение, но у него есть недостаток, заключающийся в том, что он не является встроенной техникой dict. На самом деле новый диктат, если он создан, за исключением ключа, который мы не хотим включать.
test_dict ={"sai":22,"kiran":21,"vinod":21,"sangam":21}# Printing dictionary before removal print("dictionary before performing remove is : "+ str(test_dict))# Using items() + dict comprehension to remove a dict. pair # removes vinod
new_dict ={key:val for key, val in test_dict.items()if key !='vinod'}# Printing dictionary after removal print("dictionary after remove is : "+ str(new_dict))
Вывод:
dictionary before performing remove is:{'sai':22,'kiran':21,'vinod':21,'sangam':21}
dictionary after remove is:{'sai':22,'kiran':21,'sangam':21}
Ответы:
Чтобы удалить ключ независимо от того, находится ли он в словаре, используйте форму с двумя аргументами
dict.pop()
:Это вернется,
my_dict[key]
еслиkey
существует в словаре, иNone
противном случае. Если второй параметр не указан (т. Е.my_dict.pop('key')
) Иkey
не существует, значениеKeyError
повышается.Чтобы удалить ключ, который гарантированно существует, вы также можете использовать
Это вызовет,
KeyError
если ключа нет в словаре.источник
pop()
overdel
: он возвращает значение для этого ключа. Таким образом, вы можете получить и удалить запись из dict в одной строке кода.try
/except
решение, если ключ не существует. Возможно, вам будет легче читать одну или другую, и это нормально. Оба идиоматических Python, так что выбирайте все, что вы предпочитаете. Но утверждать, что этот ответ является более сложным или неэффективным, просто не имеет смысла.self
, поэтому было бы довольно удивительно, если бы это сделал.В частности, чтобы ответить "есть ли способ сделать это в одну строку?"
... хорошо, вы спросили ;-)
Однако вы должны учитывать, что этот способ удаления объекта из a не
dict
является атомарным - возможно, что он'key'
может присутствоватьmy_dict
во времяif
оператора, но может быть удален доdel
его выполнения, и в этом случаеdel
произойдет сбой с помощью aKeyError
. Учитывая это, было бы безопаснее использоватьdict.pop
или что-то вродечто, конечно, определенно не является одной строкой.
источник
pop
это определенно более лаконично, хотя есть одно ключевое преимущество в этом: сразу понятно, что он делает.try/except
Утверждение является более дорогим. Вызывать исключение медленно.try
он немного быстрее, хотя, если нет,try
действительно намного медленнее.pop
является достаточно последовательным, но медленнее, чем все, ноtry
с отсутствующим ключом. См. Gist.github.com/zigg/6280653 . В конечном счете, это зависит от того, как часто вы ожидаете, что ключ действительно будет в словаре, и от того, нужна ли вам атомарность, и, конечно же, от того, занимаетесь ли вы преждевременной оптимизацией;)if 'key' in mydict: #then del...
. Мне нужно было извлечь ключ / val из dict для правильного разбора, pop не был идеальным решением.Мне потребовалось некоторое время, чтобы понять, что именно
my_dict.pop("key", None)
делает. Поэтому я добавлю это в качестве ответа, чтобы сэкономить время для других Google:Документация
источник
dict.pop?
в IPython.del my_dict[key]
немного быстрее, чемmy_dict.pop(key)
для удаления ключа из словаря, когда ключ существуетНо когда ключ не существует,
if key in my_dict: del my_dict[key]
это немного быстрее, чемmy_dict.pop(key, None)
. Оба по крайней мере в три раза быстрее, чемdel
вtry
/except
оператор:источник
pop
на adel
. Создание словаря полностью превзойдёт его удаление.del
иpop
из первого набора таймингов выше)Если вам нужно удалить много ключей из словаря в одной строке кода, я думаю, что использование map () довольно лаконично и читабельно на Pythonic:
И если вам нужно отлавливать ошибки, когда вы выводите значение, которого нет в словаре, используйте lambda в map () следующим образом:
или
python3
, вместо этого, вы должны использовать понимание списка:Оно работает. И «e» не вызывало ошибку, даже если у myDict не было клавиши «e».
источник
map
теперь друзья ленивы и возвращают итераторы. Использованиеmap
для побочных эффектов обычно считается плохой практикой; стандартныйfor ... in
цикл будет лучше. Посмотрите Представления И Итераторы вместо Списков для получения дополнительной информации.[myDict.pop(i, None) for i in ['a', 'c']]
, поскольку они предлагают общую альтернативуmap
(иfilter
).for ... in
цикл.map()
, которое часто используется для его побочных эффектов. Рекомендованной альтернативой в Python является понимание списка, которое, на мой взгляд, все еще вполне читабельно и когнитивно легко, как однострочный (см. Вопрос). Используемые только для побочных эффектов, обе конструкции действительно приводят к бесполезному списку, который может быть неэффективным. Начиная с Python3, я не знаю встроенной функции, которая может безопасно и элегантно выполнять итерацию по выражению генератора, без дорогостоящего побочного продукта, напримерloop(d.pop(k) for k in ['a', 'b'])
.Вы можете использовать словарное понимание, чтобы создать новый словарь с удаленным этим ключом:
Вы можете удалить по условиям. Нет ошибки, если
key
не существует.источник
Используя ключевое слово "del":
источник
Мы можем удалить ключ из словаря Python несколькими следующими способами.
Используя
del
ключевое слово; это почти такой же подход, как вы сделали, хотя -Или
Мы можем сделать как следующее:
Но следует помнить, что в этом процессе он фактически не удалит какой-либо ключ из словаря, а не исключит конкретный ключ из этого словаря. Кроме того, я заметил, что он вернул словарь, который не был упорядочен так же, как
myDict
.Если мы запустим его в оболочке, он выполнит что-то вроде
{'five': 500, 'four': 400, 'three': 300, 'two': 200}
- обратите внимание, что это не тот же порядок, что иmyDict
. Опять же, если мы попытаемся напечататьmyDict
, то увидим все ключи, включая которые мы исключили из словаря этим подходом. Однако мы можем создать новый словарь, назначив следующую переменную в переменную:Теперь, если мы попытаемся распечатать его, он будет следовать родительскому порядку:
Или
Используя
pop()
метод.Разница между
del
иpop
заключается в том, что, используяpop()
метод, мы можем при необходимости сохранить значение ключа , как показано ниже:Разместите эту суть для дальнейшего использования, если вы найдете это полезным.
источник
if myDict.get('one')
чтобы проверить, присутствует ли ключ! Сбой, если myDict ['one'] имеет значение false. Кроме того, у дикторов нет внутреннего порядка, поэтому нет смысла упоминать об этом.Вы можете использовать обработку исключений, если хотите быть очень многословным:
Однако это медленнее, чем
pop()
метод, если ключ не существует.Для нескольких клавиш это не имеет значения, но если вы делаете это неоднократно, тогда лучше использовать последний метод.
Самый быстрый подход заключается в следующем:
Но этот метод опасен, потому что если он
'key'
будет удален между двумя строками,KeyError
будет поднят.источник
Я предпочитаю неизменную версию
источник
Другой способ - использование items () + dict
items () в сочетании с пониманием dict может также помочь нам решить задачу удаления пары ключ-значение, но у него есть недостаток, заключающийся в том, что он не является встроенной техникой dict. На самом деле новый диктат, если он создан, за исключением ключа, который мы не хотим включать.
Вывод:
источник
Один фильтр на ключ
Несколько фильтров на ключах
источник