Установите значение в dict, только если значение еще не установлено

Каков самый pythonic способ установить значение в dict, если значение еще не установлено?

В настоящий момент мой код использует операторы if:

if "timeout" not in connection_settings:
    connection_settings["timeout"] = compute_default_timeout(connection_settings)

dict.get(key,default) подходит для кода, потребляющего dict, а не для кода, который готовит dict для передачи другой функции. Вы можете использовать его, чтобы установить что-то, но не более красивое imo:

connection_settings["timeout"] = connection_settings.get("timeout", \
    compute_default_timeout(connection_settings))

будет вычислять вычислительную функцию, даже если ключ содержал ключ; ошибка.

Defaultdict - это значения по умолчанию одинаковые.

Конечно, вы много раз устанавливаете примитивные значения, которые не нужны для вычислений как значения по умолчанию, и они могут, конечно, использовать dict.setdefault. Но как насчет более сложных случаев?

Ответ 1

Это немного не ответ, но я бы сказал, что самый pythonic - это оператор if, который у вас есть. Вы сопротивлялись стремлению к одному слою с помощью __setitem__ или других методов. Вы избегали возможных ошибок в логике из-за существующих, но-ложных значений, которые могут возникнуть, когда вы пытаетесь быть умными с короткозамкнутым хостом and/or. Сразу видно, что функция вычисления не используется, когда она не нужна.

Это ясно, лаконично и читаемо - питоновское.

Ответ 2

dict.setdefault точно "установит значение в dict, только если значение еще не установлено", что является вашим вопросом. Однако вам все равно нужно вычислить значение, чтобы передать его в качестве параметра, который не является тем, что вы хотите.

Ответ 3

Один из способов сделать это:

if key not in dict:
  dict[key] = value

Ответ 4

Я использую следующее, чтобы изменить значения kwargs на значения, отличные от значений по умолчанию, и перейти к другой функции:

def f( **non_default_kwargs ):

    kwargs = {
        'a':1,
        'b':2,
    }
    kwargs.update( non_default_kwargs )

    f2( **kwargs )

Это имеет достоинства, что

  • вам не нужно дважды вводить ключи

  • все выполняется в одной функции

Ответ 5

Попробуйте использовать один лайнер:

connection_settings["timeout"] ||= compute_default_timeout(connection_settings)

Ответ 6

Вероятно, вам понадобится dict.setdefault:

Создайте новый словарь и установите значение:

>>> d = {}
>>> d.setdefault('timeout', 120)
120
>>> d
{'timeout': 120}

Если уже установленное значение, dict.setdefault не переопределит его:

>>> d['port']=8080
>>> d.setdefault('port', 8888)
8080
>>> d
{'port': 8080, 'timeout': 120}