обработка возможных одновременных ошибок в Python - PullRequest
2 голосов
/ 29 мая 2019

Я только начал изучать python и хочу знать, является ли мой подход лучшим в обработке возможных одновременных ошибок.

Input object is: actor = {"name": "John Cleese", "rank": "awesome"}

Я определил функцию, которая должна возвращать слово "X" из значения свойства "Y":

def get_property(prop, poz):
    ln = actor[prop].split()[poz]
   return ln


#this is how I call my function
_prop = "fname"
_poz = 12

print("The actor's %s is %s" % (_prop, get_property(_prop, _poz)))

Моя цель состоит в том, чтобы, если свойство не существовало, тогда использовать «имя» и / или если значение не может быть разбито на столько слов, сколько значение «_poz + 1», затем выбрать первое слово значения это свойство.

Мое решение ниже, поэтому, пожалуйста, дайте мне знать, если есть лучший способ. Заранее спасибо!

# Handle all the exceptions!
#Setup
actor = {"name": "John Cleese", "rank": "awesome"}

#This function should return the "poz"th word of property "prop". If an  invalid property is passed then use "name". If an invalid index of the word in the value is passed then use return the first word. 

def get_property(prop, poz):
    ln = ""
    noerr = 0
    while noerr == 0:
        try:
            ln = actor[prop].split()[poz]
        except IndexError:
            poz = 0
        except KeyError:
            prop = "name"    
        else:
            noerr = 1
    return ln

#Test code
_prop = "fname"
_poz = 12

print("The actor's %s is %s" % (_prop, get_property(_prop, _poz)))

Это ожидаемые случаи и их вывод:

Случай 1: действительное свойство и индекс действительного слова

_prop = "name"
_poz = 1
get_property(_prop, _poz) = Cleese

Случай 2: допустимое свойство и неверный индекс слова

_prop = "name"
_poz = 12
get_property(_prop, _poz) = John 

Случай 3: Недопустимое свойство и действительный индекс слова

_prop = "MIDDLEname"
_poz = 1
get_property(_prop, _poz) = Cleese

Случай 4: Недопустимое свойство и неверный индекс слова

_prop = "b-rank"
_poz = 12
get_property(_prop, _poz) = John

1 Ответ

1 голос
/ 29 мая 2019

Что вы делаете

"Проще просить прощения, чем разрешения" EAFP

В вашем коде вы просто используете полученные параметры и надеетесь, что все работает нормально (try). Если это не так (except), измените параметр соответствующим образом и попробуйте снова (while), пока он не заработает (else).

Итак, в основном вы проверяете ввод впоследствии . Это идет с большим количеством дополнительного кода (try, except и т. Д.). Но на самом деле это предпочтительный стиль кодирования в соответствии с Python

Но в вашем случае, особенно в качестве начинающего, ваш подход имеет следующие недостатки :

  • Ваш код становится более сложным и труднее для чтения , потому что вы используете много разных методов в одной функции (try с несколькими except в цикле while)
    • Вы не можете легко определить, если вы, возможно, забыли случай!
  • Ваш код становится медленнее , чтобы выполнить (вы не почувствуете разницу в этом случае, но это полезно знать), например:
    • В худшем случае (IndexError + KeyError) вы должны пройти через while цикл 3 раза
  • Ваш код становится «небезопасным» , например:
    • Что произойдет, если изменить словарь actor и убрать ключ name? Ваш код застрял бы в бесконечном цикле, потому что конструкция try-except будет перехватывать исключение каждый раз, не выполняя случай else.

Что вы должны сделать

"Смотри, прежде чем прыгнуть" LBYL

Таким образом, лучшим решением в вашем случае будет проверка вашего ввода до того, как вы попытаетесь работать с ним.

В вашем случае вы работаете с двумя различными структурами данных (dict и list):

  • Для вашего словаря вы можете использовать метод get(key, default), чтобы безопасно получить желаемое значение из словаря
  • Для вашего списка разделенных слов вы можете проверить, достаточно ли слов с помощью метода len(list)

Эти методы помогут вам вообще избежать исключений. Просто добавьте логику в функцию get_property, чтобы убедиться, что каждый случай ошибки обрабатывается правильно:

actor = {"name": "John Cleese", "rank": "awesome"}

def get_property(prob, pos, default="name"):
    values = actor.get(prob, actor[default]).split()
    return values[pos] if pos < len(values) else values[0]

test_values = [("name", 1), ("name", 12), ("MIDDLEname", 1), ("b-rank", 12)]
for prob, pos in test_values:
    print(f"{prob}, {pos} => {get_property(prob, pos)}")

Это дает вывод:

name, 1 => Cleese
name, 12 => John
MIDDLEname, 1 => Cleese
b-rank, 12 => John
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...