Как поднять 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]
user531225
источник
5
Просто так, поднять ValueError () хахаха
slezica
@ user531225: Можете ли вы принять другой ответ, чтобы я мог удалить свой. Спасибо :)
pyfunc
@ THC4k: настолько странно, что он возвращает позицию самого правого вхождения вместо счетчика.
Джон Мачин,
@ErikAllik: Очевидно, что он сделал - он написал в StackOverflow. Что случилось с этим?
Майкл Шепер,

Ответы:

178

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

NPE
источник
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
Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, как и / или почему он решает проблему, улучшит долгосрочную ценность ответа.
Дональд Дак