Какова временная сложность оператора try в Python, учитывая, что в большинстве случаев он терпит неудачу?

У меня есть функция, в которой я хотел бы обнаружить первое вхождение любой буквы (учитывая группу букв) в строке и вернуть индекс буквы (см. Ниже).

Время имеет решающее значение, поэтому я думаю об использовании метода try / except (см. LetterDetect ниже).

Является ли это плохой практикой, зная, что оператор try в большинстве случаев терпит неудачу? Во-вторых, будет ли это более эффективным (по времени), чем проверка каждой словарной статьи на наличие каждой буквы (как в LetterDetect2)?

Возьмите следующую функцию, которая выглядит:

def LetterDetect(s, letters):
    Dct = {}
    for l in letters:
        Dct[ord(l)] = 0

    for i in range(0, length(s)):
        try:
            Dct[ord(s[i])] +=1
            return i
        except:
            pass

Против:

def LetterDetect2(s, letters):
    Dct = {}
    for l in letters:
        Dct[ord(l)] = 0

    for i in range(0, length(s)):
       if ord(s[i]) in Dct:
            return i

LetterDetect("test", "abcdt")
LetterDetect2("test", "abcdt")

Я ценю любую помощь, я новичок в кодировании и Python. Спасибо!


person DannyMoshe    schedule 22.06.2016    source источник
comment
Я бы сказал, что утверждение, которое в большинстве случаев терпит неудачу, - плохая практика. Он не очень удобочитаем, а обработка ошибок - относительно дорогая форма потока управления.   -  person John Coleman    schedule 22.06.2016


Ответы (2)


Помимо основных проблем с вашим дизайном, на которые указал Джон Гордон, я хотел бы ответить прямо на вопрос:

  1. Использование try / catch для достижения обычного управления потоком является злоупотреблением его назначением. Я могу предсказать несколько способов, которыми это может вас укусить (отладчик может остановить вас на исключении, будущий программист может «исправить» ваш код), но основное правило - используйте языковые функции в том виде, в каком они были разработаны.
  2. На практике попытка / улов будет медленной. Среда выполнения языка должна участвовать и делать всевозможные причудливые вещи, ни одна из которых вам на самом деле не нужна.
  3. Исключения должны быть в общем-то исключительными.
person Malvolio    schedule 22.06.2016

Использование словаря кажется странным способом решения этой проблемы. Есть какая-то конкретная причина, по которой вы это используете?

Строковый метод .find() https://docs.python.org/2/library/stdtypes.html#str.find кажется гораздо лучшим решением:

def LetterDetect(s, letters)
    for l in letters:
        position = s.find(l)
        if position != -1:
            return position
    return None
person John Gordon    schedule 22.06.2016
comment
Разве использование словаря не было бы более эффективным, поскольку вместо сравнения с каждой буквой в строке код будет проверять, соответствует ли он существующему ключу (относится к первой функции LetterDetect)? Или я неправильно понимаю, как словарь проверяется на существующий ключ. - person DannyMoshe; 22.06.2016
comment
@DannyMoshe Ваш код пытается подсчитать количество вхождений различных символов? В таких случаях используйте Counter: from collections import Counter; Counter(ord(c) for c in the_text). - person Bakuriu; 22.06.2016
comment
@DannyMoshe Поиск в словаре может быть более эффективным, чем проверка линейной строки, если словарь уже построен, чего нет в вашем решении. - person John Gordon; 22.06.2016
comment
@JohnGordon Я построил словарь буквенных знаков. Затем я проверяю символы в s один за другим по словарю. Это вернет ошибку для ненайденных записей, что, как я думал, может быть более эффективным, чем линейная проверка строки (в данном случае операция O (n * n)). Но похоже на то, что вы сказали, try / except будет менее эффективным. - person DannyMoshe; 22.06.2016
comment
@DannyMoshe Ваше решение выполняет двойную работу: создает словарь (который требует просмотра каждого отдельного символа в letters), затем поиск в dict. - person John Gordon; 22.06.2016
comment
@JohnGordon Но разве в худшем случае это не будет операцией O (n + n) по сравнению с операцией O (n n)? Я говорю O (n n), поскольку s.find (l) в худшем случае будет искать каждый символ в буквах в каждом символе s? - person DannyMoshe; 22.06.2016
comment
@DannyMoshe Я понимаю, к чему вы клоните. Я никогда не проводил тщательного анализа алгоритмов, поэтому не знаю настоящего ответа. Моя интуиция подсказывает, что ваше решение работает медленнее, но я могу ошибаться. - person John Gordon; 22.06.2016