2010-01-22 3 views
9

Вариант 1:какой стиль является предпочтительным?

def f1(c): 
    d = { 
    "USA": "N.Y.", 
    "China": "Shanghai" 
    } 

    if c in d: 
    return d[c] 

    return "N/A" 

Вариант 2:

def f2(c): 
    d = { 
    "USA": "N.Y.", 
    "China": "Shanghai" 
    } 

    try: 
    return d[c] 
    except: 
    return "N/A" 

Так что я могу затем вызвать:

for c in ("China", "Japan"): 
    for f in (f1, f2): 
    print "%s => %s" % (c, f(c)) 

Варианты либо определить, является ли ключ находится в директории, прежде чем руки (f1), или просто отступить к исключению (f2). Какой из них предпочтительнее? Зачем?

+8

исключая: - плохая карма. Всегда будьте конкретны в том, что вы заинтересованы в ловле, в этом случае KeyError – richo

+2

Вы выбрали плохой пример. Очевидный ответ не предполагает ни стиля. – Omnifarious

ответ

9

Как правило, исключения несут некоторые накладные расходы и предназначены для действительно «исключительных» случаев. В этом случае это звучит как обычная часть исполнения, а не состояние «исключительное» или «ошибка».

В целом, я думаю, что ваш код будет полезен с помощью соглашения «if/else» и сохранения исключений только тогда, когда они действительно необходимы.

+2

, которые напоминают мне «код, как вы думаете», «дела идут лучше, поскольку они предназначены для». поэтому я отмечаю это как ответ. –

+0

Возможно, вы правы, когда говорите, что Исключения имеют накладные расходы, но стиль python - «Лучше попросить прощения, чем разрешение». Это означает, что вы не проверяете, есть ли что-то или нет. Вы «попробуете» и сделаете это, а затем попросите прощения. Если бы это был я, я бы отправился с «try/except» –

+2

Это хорошая точка jeffjose. В питоне очень полезно попробовать что посмотреть. Однако использование предложения try/except в этом случае, когда мы не ожидаем ничего исключительного, не является хорошей идеей. Как сказал Ричо: «Плохая карма».:-) –

21

Ни, я не пошел бы на

def f2(c): 
    d = { 
    "USA": "N.Y.", 
    "China": "Shanghai" 
    } 

    return d.get(c, "N/A") 

Этот путь короче и «получить» предназначен для работы.

Также исключение без явного исключения является неправильной оценкой, поэтому используйте except KeyError: не только за исключением.

Исключения не имеют больших накладных расходов в python. Как правило, лучше использовать их, если нет более лучших альтернатив, а иногда даже когда он сохраняет поиск атрибутов (вместо использования hasattr).

Редактировать:, чтобы прояснить общий пункт об исключениях.

paxdiablo является правильным на общем плане. Python в основном предназначен для «его легче просить прощения, а затем разрешения». Попробуйте, затем посмотрите, что не получается (исключения), затем «посмотрите, прежде чем прыгать», посмотрите, что тут происходит. Это связано с тем, что поиск атрибутов в python может быть дорогостоящим, поэтому повторное использование одного и того же материала (для проверки границ) является пустой тратой ресурсов. Тем не менее, внутренние вещи в python обычно получают более приятные помощники, поэтому лучше их использовать.

+0

вопрос не специфический для dict, оно главным образом для выставки. то, что я хочу знать, - это проверить границы перед рукой или отступить к исключению. –

+1

@ Dyno: тогда вы должны были спросить * это *. Хорошее эмпирическое правило «лучше просить прощения, чем разрешение», но я добавлю, что если общий случай приведет к проси о прощении, то сначала попросите прощения. –

+0

Вы имеете в виду «просто сделайте это». если он пойдет не так, а потом поработайте с ним позже? –

7

Ни то, ни другое.

return d.get(c, 'N/A') 
11

В общих чертах (не обязательно Python), я предпочитаю метод «попробуй тогда скажи-мне-если-он-пошел-неправильно» (исключения) во всех, кроме самых простых случаев. Это связано с тем, что в поточных средах или во время доступа к базе данных базовые данные могут изменяться между проверкой ключа и извлечением значения.

Если вы не изменяете ассоциативный массив вне текущего потока, вы можете выполнить метод «check-first-then-extract».

Но это для общего случая. Здесь, в частности, вы можете использовать get метод, который позволяет указать значение по умолчанию, если ключ не существует:

return d.get (c, "N/A") 

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

+------------------------------+--------------------+ 
| Thread1      | Thread2   | 
+------------------------------+--------------------+ 
| Check is NY exists as a key. |     | 
|        | Delete NY key/val. | 
| Extract value for NY.  |     | 
+------------------------------+--------------------+ 

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

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

+0

Я всегда называл их. Его легче просить прощения, затем разрешить »и« посмотреть, прежде чем прыгать », соответственно. Но я согласен с тем, что прощение python - это то, что вам нужно. –

+0

Я склонен отмечать как этот, так и jweede как ответ, но, похоже, это не выполнимо. –

4

Я с Дэвидом на этом:

def f2(c): 
    d = { 
     "USA": "N.Y.", 
     "China": "Shanghai" 
     } 

    return d.get(c, "N/A") 

... точно, как я пишу это.

Для решения ваших других вариантов:

В «f1()», нет ничего плохого в этом, самом по себе, но словарям есть метод Get() для почти точного прецедента: «получить это от дикта, и если его там нет, верните эту другую вещь вместо этого ». Это все, что говорит ваш код, используя get(), просто более кратким.

В 'f2()', используя 'except' сам по себе, как это нахмурился, и, кроме того, вы не делаете ничего полезного в ответ на исключение - в вашем случае код вызова никогда не будет знаете, что существует исключение. Итак, зачем использовать конструкцию, если она не добавляет значения вашей функции или кода, который ее вызывает?

1

Я вижу людей, использующих «get», которые я рекомендую. Тем не менее, если вы окажетесь в подобной ситуации в будущем, поймать исключение вы имеете в виду:

try: 
    return d[k] 
except KeyError: 
    return "N/A" 

Таким образом, другие исключения (включая KeyboardInterrupt) не зацепиться. Вы почти никогда не хотите ловить KeyboardInterrupt.

0

Я согласен с тем, что в этом случае dict.get - лучшее решение.

В целом, я думаю, что ваш выбор будет зависеть от того, насколько вероятны исключения. Если вы ожидаете, что ключевые поисковые запросы в основном пройдут, то попытка/улов - лучший выбор ИМО. Точно так же, если они будут часто терпеть неудачу, утверждение if лучше.

Выполнение исключений в сравнении с атрибутами не так уж и отличается в Python, поэтому я бы больше беспокоился о логике использования исключений/look-before-you-leap, чем об аспектах производительности.

Смежные вопросы