#python #dictionary #keyerror
#python #словарь #ошибка ключа
Вопрос:
Мое понимание dict.get() заключалось в том, что если ключ существует, то оценка аргумента по умолчанию не выполняется. И несколько источников неявно оставляют такую интерпретацию. Но оказывается, что это не так.
Давайте предположим, что существует dict, который имеет целочисленные ключи либо в str, либо в int типе. Итак, одна строка для извлечения типа ключа модуля значений будет использоваться .get
со значением по умолчанию, зависящим от ключа альтернативного типа.
>>> d = {'2':4}
>>> d.get(2, d['2'])
4
>>> d.get('2', d[2])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 2
Какой смысл оценивать аргумент по умолчанию, если ключ существует?
Это просто плохой дизайн метода или я слишком обобщаю предполагаемую функциональность .get()
?
Комментарии:
1.
d[2]
вычисляется до его передачи функции.2. Поскольку d[2] не существует, выдается ошибка. Необходимо передать действительное значение по умолчанию в dict.get.
Ответ №1:
Основное отличие в этом случае заключается в том, что выражение d[2]
должно быть вычислено до того, как оно будет передано в качестве аргумента get
функции.
Возникает исключение, потому что вы ссылаетесь в этом выражении на целочисленный ключ 2
, который не существует, прежде чем проверять d['2']
, существует ли ключ в этом словаре.
Пожалуйста, найдите ссылку: Выражения 6.3.4. Вызовы
Первичный должен вычисляться до вызываемого объекта (пользовательские функции, встроенные функции, … и все объекты, имеющие метод __call__(), являются вызываемыми). Все выражения аргументов вычисляются перед попыткой вызова.
Ответ №2:
Python не является ленивым языком, поэтому все аргументы функции оцениваются перед вызовом функции. Это означает, что во втором примере d[2]
он будет оцениваться перед вызовом d.get
. Существуют языки (например, Haskell), которые будут принимать этот код, поскольку аргументы оцениваются только по мере необходимости.
Комментарии:
1. какие-либо указатели на страницы документации python об этом?
2. @FiboKowalsky Проверьте 3-й абзац здесь: docs.python.org/3/reference/expressions.html#calls («Все выражения аргументов вычисляются перед попыткой вызова»)
Ответ №3:
Аргумент всегда вычисляется, и я не знаю ни одного процедурного языка основного потока, который позволял бы объявлять функции, чтобы оценка параметров была отложена до тех пор, пока каким-либо образом не будет решена явно.
Как отложить оценку:
d = { '2': 4 }
x = d.get('3', lambda: d[2])
print(x() if callable(x) else x)
.. но это довольно глупый пример.
Редактировать: еще один (опасный) способ отложить оценку:
x = d.get('2', False) or d[2]
.. предполагая, что нет действительных результатов от dict, оценивающих False
(например 0
, или None
). Это очень хороший способ выстрелить себе в ногу.
Комментарии:
1. это интересный способ отложить оценку. без if-предложения это было бы аккуратнее.
2. @FiboKowalsky добавил еще один способ для вашего удовольствия.
3. @Jukka_Vaisanen, круто! Я не знал, как логические операторы работают, например, с числами. Я думал
3 or 5
, что оценивает значение True, но оно оказывается равным 3. docs.python.org/3/reference/expressions.html#or