Документация по Python

Анти-паттерны Python

В: Документация по Python

Переусердствовать, кроме пункта

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

try:
    res = get_result()
    res = res[0]
    log('got result: %r' % res)
except:
    if not res:
        res = ''
    print('got exception') 

Этот пример демонстрирует 3 симптома антипаттерна:

  1. За except без указания типа исключения (строка 5) будет ловить даже здоровые исключения, в том числе KeyboardInterrupt.Это предотвратит выход из программы в некоторых случаях.
  2. Кроме блока не ререйз ошибки, а это означает , что мы не сможем сказать , если исключение пришло в get_result или потому , что res был пустой список.
  3. Хуже всего то, что если мы беспокоились о том, что результат окажется пустым, мы стали причиной чего-то гораздо худшего. Если get_result не удается, res будет оставаться полностью снято с охраной, а также ссылка на res в блоке , за исключением, поднимет NameError , полностью маскирует первоначальную ошибку.

Всегда думайте о типе исключения, которое вы пытаетесь обработать. Дайте странице Исключения для чтения и получить ощущение того, что существуют основные исключения.

Вот исправленная версия примера выше:

import traceback

try:
    res = get_result()
except Exception: 
    log_exception(traceback.format_exc())
    raise
try:
    res = res[0]
except IndexError:
    res = ''

log('got result: %r' % res) 

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

Глядя, прежде чем прыгнуть с интенсивной процессорной функцией

Программа может легко тратить время, многократно вызывая функцию с интенсивным использованием процессора.

Например, возьмем функцию , которая выглядит следующим образом : он возвращает целое число , если входное value не может производить один, еще None :

def intensive_f(value): # int -> Optional[int]
   # complex, and time-consuming code
   if process_has_failed:
       return None
   return integer_output

 

И это можно использовать следующим образом:

x = 5
if intensive_f(x) is not None:
    print(intensive_f(x) / 2)
else:
    print(x, "could not be processed")

print(x)

 

Несмотря на то , что это будет работать, то есть проблема вызова intensive_f , которая удваивает продолжительность времени код для запуска. Лучшим решением было бы получить возвращаемое значение функции заранее.

x = 5
result = intensive_f(x)
if result is not None:
    print(result / 2)
else:
    print(x, "could not be processed")

Тем не менее, более четкий и , возможно , более вещий способ заключается в использовании исключений, например:

x = 5
try:
    print(intensive_f(x) / 2)
except TypeError: # The exception raised if None + 1 is attempted
    print(x, "could not be processed")

Здесь никакая временная переменная не требуется. Это часто может быть предпочтительнее использовать assert заявление, и поймать AssertionError вместо этого.

Словарь ключей

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

bird_speeds = get_very_long_dictionary()

if "european swallow" in bird_speeds:
    speed = bird_speeds["european swallow"]
else:
    speed = input("What is the air-speed velocity of an unladen swallow?")

print(speed)

с:

bird_speeds = get_very_long_dictionary()

try:
    speed = bird_speeds["european swallow"]
except KeyError:
    speed = input("What is the air-speed velocity of an unladen swallow?")

print(speed)

В первом примере необходимо дважды просмотреть словарь, и, поскольку это длинный словарь, это может занять много времени каждый раз. Второе требует только одного поиска в словаре и, таким образом, экономит много процессорного времени.

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

Еще от кодкамп
Замечательно! Вы успешно подписались.
Добро пожаловать обратно! Вы успешно вошли
Вы успешно подписались на кодкамп.
Срок действия вашей ссылки истек.
Ура! Проверьте свою электронную почту на наличие волшебной ссылки для входа.
Успех! Ваша платежная информация обновлена.
Ваша платежная информация не была обновлена.