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

Введение

Примеры

  • 5

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

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

     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) 

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

  • 1

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

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

    Например, возьмем функцию , которая выглядит следующим образом : он возвращает целое число , если входное 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) , однако многие обстоятельства могут потребовать более сложные операции , которые необходимо сделать в случае, когда ключ нет

Синтаксис

Параметры

Примечания