Jak podnieść ValueError?

115

Mam ten kod, który znajduje największy indeks określonego znaku w ciągu, jednak chciałbym, aby podniósł a, ValueErrorgdy określony znak nie występuje w ciągu.

Więc coś takiego:

contains('bababa', 'k')

spowodowałoby:

ValueError: could not find k in bababa

W jaki sposób mogę to zrobić?

Oto aktualny kod mojej funkcji:

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

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

  return list[-1]
user531225
źródło
5
Tak po prostu, podnieś ValueError () hahaha
slezica
@ user531225: Czy możesz zaakceptować inną odpowiedź, abym mógł usunąć swoją. Dzięki :)
pyfunc
@ THC4k: Tak dziwne, że zamiast liczby zwraca pozycję najbardziej prawego wystąpienia.
John Machin,
@ErikAllik: Oczywiście, że tak - wysłał do StackOverflow. Co z tym jest nie tak?
Michael Scheper

Odpowiedzi:

178

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

NPE
źródło
2
Czy wiesz, że jeśli nie chcesz używać wiadomości, możesz po prostu raise ValueErrorzamiast tego raise ValueError()?
Tomasz Gandor
27

Oto poprawiona wersja twojego kodu, która nadal działa, a ponadto pokazuje, jak podnieść ValueErrorpoziom tak, jak chcesz. Swoją drogą, myślę find_last(), find_last_index()lub coś podobnego byłoby bardziej opisową nazwą tej funkcji. Dodatkowym utrudnieniem jest fakt, że Python ma już metodę obiektu kontenera o nazwie, __contains__()która robi coś innego, testując członkostwo.

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'

Aktualizacja - znacznie prostszy sposób

Łał! Oto znacznie bardziej zwięzła wersja - zasadniczo jednolinijkowa - która prawdopodobnie jest również szybsza, ponieważ odwraca (przez [::-1]) ciąg przed wykonaniem wyszukiwania w przód w nim w poszukiwaniu pierwszego pasującego znaku i robi to przy użyciu szybkiej wbudowanej index()metody łańcuchowej . Odnosząc się do twojego rzeczywistego pytania, miłym małym ułatwieniem związanym z używaniem index()jest to, że już podnosi się, ValueErrorgdy podciąg znaku nie jest znaleziony, więc nic więcej nie jest wymagane, aby to się stało.

Tutaj jest wraz z szybkim testem jednostkowym:

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
martineau
źródło
2. funkcja: OP potrzebuje / chce forpętli. 1. funkcja: FAIL dla contains('foo', 'f').
John Machin,
1
@John Machin: Naprawiono błąd znaleziony w pierwszej funkcji, dziękuję za zwrócenie mi na to uwagi. Nie widzę niczego w pytaniu OP ani w komentarzach pod nim, co wskazywałoby, że potrzebują lub chcą forpętli w odpowiedzi, chociaż zdarza się, że pojawia się w ich własnym kodzie. Tak czy inaczej mój 1. Funkcja Pokazuje im, jak gdy znak nie zostanie znaleziony, która jest co prosili. i zilustrowałem, jak to zrobić w kontekście pliku . Nawet jeśli z jakiegoś powodu chcą , myślę, że inni mogą uznać drugą wersję bez jednej przynajmniej za nieco interesującą. raiseValueErrorforfor
martineau
„Chcę użyć pętli for :-)” był wczesnym komentarzem do usuniętej teraz odpowiedzi autorstwa @pyfunc
John Machin
1
@John Machin: Nie myśl, że mogę zostać pociągnięty do odpowiedzialności za nie honorowanie próśb w komentarzach do usuniętych odpowiedzi, których nie widziałem i których nie widzę. Jednak, mimo że mój 2 funkcja nie używać forpętli, to nie w sposób odpowiedzieć na pytanie o rzeczywiste Jak gdy postać nie znajduje się w ciąg - mianowicie wywołując coś innego, że zrobi to za Ciebie. Istnieje również perspektywa, że ​​OP może poradzić sobie ze swoim naprawieniem lub czymkolwiek to jest po zobaczeniu rozwiązania sans lub późniejszym zaznajomieniu się z Pythonem. raiseValueErrorforfor
martineau
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
>>>
John Machin
źródło
4
>>> response='bababa'
...  if "K" in response.text:
...     raise ValueError("Not found")
Kaushik Dey
źródło
1
Chociaż ten kod może odpowiedzieć na pytanie, dostarczenie dodatkowego kontekstu dotyczącego tego, jak i / lub dlaczego rozwiązuje problem, poprawiłoby długoterminową wartość odpowiedzi.
Kaczor Donald