Подтвердить что ты не робот

Определите, присутствует ли ключ в словаре

Возможный дубликат:
'has_key()' или 'in'?

У меня есть словарь Python, например:

mydict = {'name':'abc','city':'xyz','country','def'}

Я хочу проверить, находится ли ключ в словаре или нет. Я очень хочу знать, что предпочтительнее из следующих двух случаев и почему?

1> if mydict.has_key('name'):
2> if 'name' in mydict:
4b9b3361

Ответ 1

if 'name' in mydict:

является предпочтительной, питонической версией. Использование has_key() не рекомендуется, и этот метод был удален в Python 3.

Ответ 2

В том же духе, что и ответ Мартино, лучшее решение часто не проверяется. Например, код

if x in d:
    foo = d[x]
else:
    foo = bar

обычно записывается

foo = d.get(x, bar)

который короче и более прямо говорит о том, что вы имеете в виду.

Другим распространенным случаем является что-то вроде

if x not in d:
    d[x] = []

d[x].append(foo)

который можно переписать

d.setdefault(x, []).append(foo)

или переписать еще лучше, используя collections.defaultdict(list) для d и записывая

d[x].append(foo)

Ответ 3

В терминах байт-кода in сохраняет LOAD_ATTR и заменяет a CALL_FUNCTION на COMPARE_OP.

>>> dis.dis(indict)
  2           0 LOAD_GLOBAL              0 (name)
              3 LOAD_GLOBAL              1 (d)
              6 COMPARE_OP               6 (in)
              9 POP_TOP             


>>> dis.dis(haskey)
  2           0 LOAD_GLOBAL              0 (d)
              3 LOAD_ATTR                1 (haskey)
              6 LOAD_GLOBAL              2 (name)
              9 CALL_FUNCTION            1
             12 POP_TOP             

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

С точки зрения производительности, время отражает код операции

$ python -mtimeit -s'd = dict((i, i) for i in range(10000))' "'foo' in d"
 10000000 loops, best of 3: 0.11 usec per loop

$ python -mtimeit -s'd = dict((i, i) for i in range(10000))' "d.has_key('foo')"
  1000000 loops, best of 3: 0.205 usec per loop

in почти в два раза быстрее.

Ответ 4

Мой ответ "ни один".

Я считаю, что самый "путинский" способ делать вещи - НЕ проверять заранее, если ключ находится в словаре, а вместо этого просто писать код, который предполагает его там, и поймать любые KeyErrors, которые возникают, потому что это не так.

Обычно это делается с приложением кода в предложении try...except и является хорошо известной идиомой, обычно выражаемой как " Легче просить прощения, чем разрешение" или с аббревиатурой EAFP, что в основном означает, что лучше попробовать что-то и поймать ошибки вместо этого, чтобы убедиться, что все ОК, прежде чем что-либо делать. Зачем проверять, что не нужно проверять, когда вы можете обрабатывать исключения изящно, а не пытаться их избежать? Поскольку он часто читается и код имеет тенденцию быть более быстрым, если вероятность низкая, что ключ не будет там (или любые предпосылки там могут быть).

Конечно, это не уместно во всех ситуациях, и не все согласны с философией, поэтому вам нужно будет решить для себя в каждом конкретном случае. Неудивительно, что противоположность этого называется LBYL для "Look Before You Leap".

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

if 'name' in dct:
    value = dct['name'] * 3
else:
    logerror('"%s" not found in dictionary, using default' % name)
    value = 42

против

try:
    value = dct['name'] * 3
except KeyError:
    logerror('"%s" not found in dictionary, using default' % name)
    value = 42

Хотя в этом случае почти точно такое же количество кода, второе не проверяет время сначала и, вероятно, немного быстрее из-за него (попробуйте... кроме того, блок не полностью свободен, хотя, возможно, это возможно здесь не так много).

Вообще говоря, тестирование заранее часто может быть гораздо более значительным, и выигрыш в экономии от его не может быть значительным. Тем не менее, if 'name' in dict: лучше по причинам, указанным в других ответах.

Если вы заинтересованы в этой теме, сообщение под названием "EAFP vs LBYL (было Re: немного разочаровано до сих пор)" из архива списка рассылки Python, вероятно, объясняет разницу между двумя подходами лучше, чем у меня здесь. Там также было хорошее обсуждение двух подходов в книге Python в двух словах, 2-е изд. Alex Martelli в главе об исключениях под названием " Стратегии проверки ошибок".