Понимание Dict с условием if-else, похоже, вообще не использует блок if. Он всегда переходит в блок else, даже если не должен.
Я пытаюсь использовать понимание dict с условием if в python, чтобы определить количество вхождений символов в строку. Однако условие if никогда не кажется выполненным (когда оно действительно должно быть выполнено). Кажется, что выполнено только условие else
def letter_count(input_str):
letter_count_map = {}
letter_count_map = {letter: letter_count_map[letter]+1 if letter in
letter_count_map.keys() else 1
for letter in input_str}
print(letter_count_map)
letter_count("serendipity")
Ожидаемый результат:
{'s': 1, 'e': 2, 'r': 1, 'n': 1, 'd': 1, 'i': 2, 'p': 1, 't': 1, 'y': 1}
Фактический результат:
{'s': 1, 'e': 1, 'r': 1, 'n': 1, 'd': 1, 'i': 1, 'p': 1, 't': 1, 'y': 1}
Что я делаю неправильно?
letter_count_map
не присваивается новое значение до тех пор, пока понимание dict
не будет полностью оценено. До того, как это произойдет, это просто пустой dict
, и поэтому в его keys()
ничего не будет. То, что вы пытаетесь сделать, должно выполняться с помощью цикла вместо понимания:
letter_count_map = {}
for letter in input_str:
letter_count_map[letter] = letter_count_map[letter]+1 if letter in letter_count_map.keys() else 1
Примечание: letter_count_map[letter]+1 if letter in letter_count_map.keys() else 1
— это В самом деле медленный/многословный способ написания letter_count_map.get(letter, 0) + 1
.
@ShadowRanger спасибо за ответ. Чтобы уточнить, вы говорите, что letter_count_map.get(letter, 0) + 1
более эффективен? Если да, то почему он более производительный?
@GopinathTaget: он позволяет избежать создания ненужного представления ключей (хотя вы можете удалить .keys()
из исходного кода, чтобы получить тот же эффект), избегает проверки сдерживания с последующим поиском в пользу простого поиска и избегает инструкций ветвления байт-кода. Это может быть не намного быстрее (вызовы методов имеют раздражающе высокие фиксированные накладные расходы, хотя они были уменьшены в 3.7, если вы вызываете с чисто позиционными аргументами), но это много короче/четче.
Вы также можете использовать defaultdict
, чтобы упростить код.
from collections import defaultdict
def letter_count(input_str):
letter_count_map = defaultdict(lambda: 0)
for c in input_str:
letter_count_map[c] += 1
print(letter_count_map)
letter_count("serendipity")
Спасибо за фрагмент. Я это проверю.
К вашему сведению, defaultdict(int)
достигнет той же цели. Не нужно lambda
.
Или даже короче: collections.Counter("serendipity")
Все зависит от того, пишете ли вы код, чтобы учиться, или у вас есть реальная проблема, которую нужно решить.
@pylang Спасибо за указатель. Проверим.