Как поднять ValueError?


115

У меня есть этот код, который находит наибольший индекс определенного символа в строке, однако я хотел бы, чтобы он поднимал, ValueErrorкогда указанный символ не встречается в строке.

Так что примерно так:

contains('bababa', 'k')

приведет к:

→ ValueError: could not find k in bababa

Как я могу это сделать?

Вот текущий код моей функции:

def contains(string,char):
  list = []

  for i in range(0,len(string)):
      if string[i] == char:
           list = list + [i]

  return list[-1]

5
Просто так, поднять ValueError () хахаха
— slezica

@ user531225: Можете ли вы принять другой ответ, чтобы я мог удалить свой. Спасибо :)
— pyfunc

@ THC4k: настолько странно, что он возвращает позицию самого правого вхождения вместо счетчика.
— Джон Мачин,

@ErikAllik: Очевидно, что он сделал - он написал в StackOverflow. Что случилось с этим?
— Майкл Шепер,

Ответы:


178

raise ValueError('could not find %c in %s' % (ch,str))


2
Знаете ли вы, что если вы не хотите использовать сообщение, вы можете просто raise ValueErrorвместо raise ValueError()?
— Tomasz

27

Вот исправленная версия вашего кода, которая все еще работает, плюс она показывает, как поднять ValueErrorтак, как вы хотите. Кстати, думаю find_last(), find_last_index()или что-то похожее было бы более наглядным названием для этой функции. Возможная путаница усугубляется тем фактом, что в Python уже есть именованный метод объекта-контейнера, __contains__()который делает что-то немного другое с точки зрения тестирования членства.

def contains(char_string, char):
    largest_index = -1
    for i, ch in enumerate(char_string):
        if ch == char:
            largest_index = i
    if largest_index > -1:  # any found?
        return largest_index  # return index of last one
    else:
        raise ValueError('could not find {!r} in {!r}'.format(char, char_string))

print(contains('mississippi', 's'))  # -> 6
print(contains('bababa', 'k'))  # ->
Traceback (most recent call last):
  File "how-to-raise-a-valueerror.py", line 15, in <module>
    print(contains('bababa', 'k'))
  File "how-to-raise-a-valueerror.py", line 12, in contains
    raise ValueError('could not find {} in {}'.format(char, char_string))
ValueError: could not find 'k' in 'bababa'

Обновление - существенно более простой способ

Вот Это Да! Вот гораздо более краткая версия - по сути, однострочная - которая также, вероятно, быстрее, потому что она меняет (через [::-1]) строку перед выполнением прямого поиска по ней для первого совпадающего символа, и это делается с помощью быстрого встроенного строкового index()метода , Что касается вашего фактического вопроса, приятное небольшое дополнительное удобство, которое приходит с использованием, index()заключается в том, что он уже вызывает, ValueErrorкогда символьная подстрока не найдена, поэтому для этого не требуется ничего дополнительного.

Вот он вместе с быстрым модульным тестом:

def contains(char_string, char):
    #  Ending - 1 adjusts returned index to account for searching in reverse.
    return len(char_string) - char_string[::-1].index(char) - 1

print(contains('mississippi', 's'))  # -> 6
print(contains('bababa', 'k'))  # ->
Traceback (most recent call last):
  File "better-way-to-raise-a-valueerror.py", line 9, in <module>
    print(contains('bababa', 'k'))
  File "better-way-to-raise-a-valueerror", line 6, in contains
    return len(char_string) - char_string[::-1].index(char) - 1
ValueError: substring not found

2-я функция: OP требует / хочет forцикл. 1-я функция: FAIL для contains('foo', 'f').
— Джон Мачин,

1
@John Machin: исправлена ​​ошибка, обнаруженная в 1-й функции, спасибо, что обратила на нее мое внимание. Я не вижу ничего в вопросе OP или в комментариях под ним, что указывает на то, что им нужен или нужен forцикл в ответе, хотя он действительно появляется в их собственном коде. Так или иначе мои 1 - функция показывает им , как , когда символ не найден , который является то , что они просили. и я проиллюстрировал, как это сделать в контексте файла . Даже если они по какой-то причине захотят получить его , я думаю, что другие могут найти вторую версию без нее, по крайней мере, несколько интересной. raiseValueErrorforfor
— Мартино,

«Я хочу использовать цикл for :-)» был ранним комментарием к теперь удаленному ответу @pyfunc
— Джон Мачин

1
@John Machin: Не думайте, что меня можно привлечь к ответственности за невыполнение запросов в комментариях к удаленным ответам, которые я не видел и не вижу. Тем не менее, даже если моя вторая функция не использует forцикл, он делает таким образом ответить на актуальный вопрос о том , как к , когда символ не найден в строке , а именно - по телефону что - то еще , что делает это для вас. Также существует вероятность того, что OP может преодолеть свою фиксацию или что-то еще после того, как увидит безразличное решение или позже станет более знакомым с Python. raiseValueErrorforfor
— Мартино

12
>>> def contains(string, char):
...     for i in xrange(len(string) - 1, -1, -1):
...         if string[i] == char:
...             return i
...     raise ValueError("could not find %r in %r" % (char, string))
...
>>> contains('bababa', 'k')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in contains
ValueError: could not find 'k' in 'bababa'
>>> contains('bababa', 'a')
5
>>> contains('bababa', 'b')
4
>>> contains('xbababa', 'x')
0
>>>

4
>>> response='bababa'
...  if "K" in response.text:
...     raise ValueError("Not found")

1
Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, как и / или почему он решает проблему, улучшит долгосрочную ценность ответа.
— Дональд Дак
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.