python get key для dict оценивает часть defulat, даже если ключ существует

#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