Шаг 163.
Python: тонкости программирования.
Трюки со словарем. Значения словаря, принимаемые по умолчанию

    На этом шаге мы рассмотрим особенности использования метода get().

    У словарей Python есть метод get() для поиска ключа, которому передают запасное значение. Это может пригодиться в самых разных ситуациях. Приведем простой пример. Предположим, что у нас есть представленная ниже структура данных, которая ставит идентификаторы в соответствие именам пользователей:

>>> name_for_userid = {
	382: 'Элис',
	950: 'Боб',
	590: 'Дилберт',
	}

    Теперь мы хотели бы использовать эту структуру данных, чтобы написать функцию greeting(), которая будет возвращать пользователю приветствие на основе его идентификатора. Наша первая реализация может выглядеть примерно так:

>>> def greeting(userid):
	return 'Привет, %s!' % name_for_userid[userid]

    В ней представлен прямолинейный поиск в словаре. Это первая реализация технически работает - но только если идентификатор пользователя является допустимым ключом в словаре name_for_userid. Если в функцию greeting() передать недопустимый идентификатор пользователя, то она вызовет исключение:

>>> greeting(382)
'Привет, Элис!'
>>> greeting(33333333)
Traceback (most recent call last):
.   .   .   .
KeyError: 33333333

    Исключение KeyError - это совсем не тот результат, который мы хотели бы видеть. Было бы намного лучше, если бы в качестве запасного варианта функция возвращала универсальное приветствие, если идентификатор пользователя не может быть найден.

    Давайте реализуем эту идею. Наш первый подход мог бы заключаться в простой проверке принадлежности в формате ключ в словаре (key in dict) и возврате приветствия по умолчанию, если идентификатор пользователя неизвестен:

>>> def greeting(userid):
	if userid in name_for_userid:
		return 'Привет, %s!' % name_for_userid[userid]
	else:
		return 'Привет всем!'

    Давайте посмотрим, как эта реализация функции greeting() проявит себя с нашими предыдущими тестовыми случаями:

>>> greeting(382)
'Привет, Элис!'
>>> greeting(33333333)
'Привет всем!'

    Намного лучше. Мы теперь получаем универсальное приветствие для неизвестных пользователей, и мы поддерживаем персонализированное приветствие, когда допустимый идентификатор пользователя найден.

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

    Более эффективная реализация, которая следует принципам EAFP, могла бы вместо выполнения явной проверки на принадлежность ключа словарю задействовать блок try ... except, чтобы поймать исключение KeyError:

>>> def greeting(userid):
	try:
		return 'Привет, %s!' % name_for_userid[userid]
	except KeyError:
		return 'Привет всем'

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

    Но мы до сих пор можем улучшить ее и предложить более чистое решение. В словаре Python есть метод get(), поддерживающий параметр "по умолчанию", который можно использовать в качестве запасного значения:

>>> def greeting(userid):
	return 'Привет, %s!' % name_for_userid.get(userid, 'всем')


См. документацию Python "dict.get()": https://docs.python.org/3/tutorial/datastructures.html#dictionaries.

    Во время вызова метода get() он проверяет, существует ли заданный ключ в словаре. Если это так, то возвращается значение, соответствующее этому ключу. Если же он не существует, то вместо этого возвращается значение по умолчанию. Как вы видите, эта реализация функции greeting() по-прежнему работает как надо:

>>> greeting(950)
'Привет, Боб!'
>>> greeting(333333)
'Привет, всем!'

    Наша заключительная реализация функции greeting() является сжатой, чистой и использует средства только из стандартной библиотеки Python. Поэтому для этой конкретной ситуации такое решение является наилучшим.

    На следующем шаге мы подитожим изученный материал.




Предыдущий шаг Содержание Следующий шаг