Ответ 1
if 'name' in mydict:
является предпочтительной, питонической версией. Использование has_key()
не рекомендуется, и этот метод был удален в Python 3.
Возможный дубликат:
'has_key()' или 'in'?
У меня есть словарь Python, например:
mydict = {'name':'abc','city':'xyz','country','def'}
Я хочу проверить, находится ли ключ в словаре или нет. Я очень хочу знать, что предпочтительнее из следующих двух случаев и почему?
1> if mydict.has_key('name'):
2> if 'name' in mydict:
if 'name' in mydict:
является предпочтительной, питонической версией. Использование has_key()
не рекомендуется, и этот метод был удален в Python 3.
В том же духе, что и ответ Мартино, лучшее решение часто не проверяется. Например, код
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)
В терминах байт-кода 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
почти в два раза быстрее.
Мой ответ "ни один".
Я считаю, что самый "путинский" способ делать вещи - НЕ проверять заранее, если ключ находится в словаре, а вместо этого просто писать код, который предполагает его там, и поймать любые 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 в главе об исключениях под названием " Стратегии проверки ошибок".