Самый Pythonic способ проверки, если значение в словаре определено/имеет нулевую длину

Скажем, у меня есть словарь, и я хочу проверить, не привязан ли ключ к непустому значению. Одним из способов сделать это будет функция len:

mydict = {"key" : "value", "emptykey" : ""}
print "True" if len(mydict["key"]) > 0 else "False"  # prints true
print "True" if len(mydict["emptykey"]) > 0 else "False"  # prints false

Однако можно полагаться на семантику Python, и как если бы объект был определен, он оценивал значение true и не оставлял вызов len:

mydict = {"key" : "value", "emptykey" : ""}
print "True" if mydict["key"] else "False"  # prints true
print "True" if mydict["emptykey"] else "False"  # prints false

Однако я не уверен, что больше Pythonic. Первый считает, что "явный лучше, чем неявный", однако второй считает, что "простой лучше, чем сложный".

Я также задаюсь вопросом, может ли отказ от вызова len укусить меня, поскольку я использую dict, который не обязательно содержит строки, но может содержать другие доступные типы (списки, наборы и т.д.). OTOH, в первом (с вызовом len), если None будет сохранен как значение, код будет взорван, тогда как версия non-len будет работать как ожидалось (будет eval до false).

Какая версия более безопасна и более Pythonic?

Изменить: уточнить предположения: я знаю, что ключ находится в словаре, и я знаю, что значения будут доступными. Я также не могу избежать ввода значений нулевой длины в словарь.

Редактировать # 2: Кажется, что людям не хватает точки моего вопроса. Я не пытаюсь определить самый Pythonic/самый безопасный способ проверки наличия ключа в словаре, я пытаюсь проверить, имеет ли значение нулевой длины или нет

Ответы

Ответ 1

Если вы знаете, что ключ находится в словаре, используйте

if mydict["key"]:
    ...

Это просто, легко читается и говорит: "Если значение, связанное с" ключом ", оценивается как True, сделайте что-нибудь". Важно знать, что типы контейнеров (dict, list, tuple, str и т.д.) Оцениваются только True, если их len больше 0.

Он также поднимет KeyError, если ваша предпосылка о том, что ключ находится в mydict, нарушен.

Все это делает его Pythonic.

Ответ 2

print (bool(mydict.get('key')))

или в выражении if:

print ('True' if mydict.get('key') else 'False')

Если вы не присутствуете, это ошибка (т.е. вы ожидаете, что она будет там), вы должны выбрать решение # 2, т.е.

print ('True' if mydict['key'] else 'False')

Это позволяет mydict['key'] выбирать наиболее эффективное определение для пустого. Для некоторых объектов (например, в кластерах) определение фактической длины является довольно сложной операцией, тогда как просто определить, является ли объект пустым или нет.

Вы также можете сравнить с '', т.е. mydict['key'] == '', чтобы сделать ваше выражение достаточно ясным. Использование len работает, но не является интуитивным.

В заключение, оставьте его проверяемому объекту, чтобы определить, пуст ли он или нет, и просто отбросьте его на bool.

Ответ 3

Из здесь:

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

Думаю, можно с уверенностью сказать, что прямое оценивание - это ваш лучший вариант - хотя, как сказал @phihag, безопаснее использовать get вместо этого, так как он защитит вас от KeyError.

Ответ 4

Я бы использовал вариант первого варианта:

>>> mydict = {"key" : "value", "emptykey" : ""}
>>> print bool(mydict["key"])
True
>>> print bool(mydict["emptykey"])
False

Любой класс, который предоставляет __len__, может быть преобразован в логическое значение напрямую (см. Проверка достоверности истинности), поэтому bool(container) является эквивалентом of bool(len(container)). Длина 0 станет булевым False, а все остальные длины будут True. У вас никогда не будет объекта с отрицательной длиной. Кроме того, логические значения True и False могут быть напечатаны непосредственно через print, поэтому вам не требуется условное выражение.

Ответ 5

Название и первое предложение фактически выражают два немного разных вопроса.

Для титульного вопроса

Самый Pythonic способ проверить, определено ли значение в словаре

Я бы пошел с

"key" in mydict

и для второго вопроса

Скажем, у меня есть словарь, и я хочу проверить, не привязан ли ключ к непустому значению.

Я бы пошел с

"key" in mydict and bool(mydict["key"])

Первая часть которой проверяет, присутствует ли "ключ" в mydict, а вторая часть возвращает true для всех значений "ключ", а затем False, None, пустая строка, пустой словарь, пустой список и 0.

Ответ 6

Самый Pythonic-способ состоит в том, чтобы не определять значение undefined (хотя он зависит от того, для чего вы его используете) и используйте in:

mydict = {"key" : "value"}
print "True" if "key" in mydict else "False"  # prints true
print "True" if "emptykey" in mydict else "False"  # prints false

В противном случае у вас есть три варианта:

  • Используйте mydict.get. Вы должны использовать это, если ключ может быть или не быть в словаре.
  • Используйте mydict[key]. Вы должны использовать это, если вы уверены, что ключ, который вы хотите, находится в dict.
  • Используйте len(mydict[key]) > 0. Это работает, только если значение имеет __len__. Обычно значение истины значения контейнера в любом случае зависит от __len__, поэтому предпочтительные выше.

Ответ 7

Из ваших двух примеров я предпочитаю второй.

Однако я не рекомендую хранить пустые ключи. Также здесь был бы полезен defaultdict:

>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> d[1].append(1)
>>> 1 in d
True

Если вы должны хранить пустые ключи, вам не нужны строковые значения "True" и "False". Просто сделайте следующее:

print bool(mydict[key])

Ответ 8

Ваши начальные условия не являются Pythonic. Почему вы храните ключ с пустым значением? Вы можете удалить ключ, а не устанавливать его на None?

Путь Pythonic - проверить существование ключа с помощью if key in dictionary, не проверяя непустое значение.