¿Cómo generar un ValueError?

115

Tengo este código que encuentra el índice más grande de un carácter específico en una cadena, sin embargo, me gustaría generar un ValueErrorcuando el carácter especificado no aparece en una cadena.

Entonces algo como esto:

contains('bababa', 'k')

daría como resultado un:

ValueError: could not find k in bababa

¿Cómo puedo hacer esto?

Aquí está el código actual para mi función:

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

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

  return list[-1]
usuario531225
fuente
5
Solo así, aumente ValueError () jajaja
slezica
@ user531225: ¿Puedes aceptar otra respuesta para que pueda eliminar la mía? Gracias :)
pyfunc
@ THC4k: Tan extraño que devuelve la posición de la aparición más a la derecha en lugar del recuento.
John Machin
@ErikAllik: Obviamente, lo hizo, publicó en StackOverflow. ¿Qué está mal con eso?
Michael Scheper

Respuestas:

178

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

NPE
fuente
2
¿Sabías que, si no quieres usar el mensaje, puedes raise ValueErrorhacerlo en lugar de hacerlo raise ValueError()?
Tomasz Gandor
27

Aquí hay una versión revisada de su código que aún funciona y además ilustra cómo generar una de ValueErrorla manera que desee. Por cierto, creo find_last(), find_last_index()o algo similar sería un nombre más descriptivo para esta función. A la posible confusión se suma el hecho de que Python ya tiene un método de objeto contenedor llamado __contains__()que hace algo un poco diferente, en cuanto a pruebas de pertenencia.

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'

Actualización: una forma sustancialmente más sencilla

¡Guauu! Aquí hay una versión mucho más concisa, esencialmente de una sola línea, que probablemente también sea más rápida porque invierte (a través de [::-1]) la cadena antes de realizar una búsqueda hacia adelante a través de ella para el primer carácter coincidente y lo hace utilizando el index()método de cadena incorporado rápido . Con respecto a su pregunta real, una pequeña ventaja adicional que viene con el uso index()es que ya genera un ValueErrorcuando no se encuentra la subcadena de caracteres, por lo que no se requiere nada adicional para que eso suceda.

Aquí está junto con una prueba unitaria rápida:

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
fuente
2ª función: El OP necesita / quiere un forbucle. 1ª función: FALLO para contains('foo', 'f').
John Machin
1
@John Machin: Se corrigió el error que encontró en la primera función, gracias por avisarme. No veo nada en la pregunta del OP o en los comentarios debajo de él que indique que necesitan o quieren un forbucle en una respuesta, aunque uno aparece en su propio código. De todos modos mis 1ª función les muestra cómo raiseun ValueErrorcuando no se encuentra el carácter que es lo que pidieron. y he ilustrado cómo hacerlo en el contexto de a for. Incluso si quieren una forpor alguna razón, creo que otros pueden encontrar la segunda versión sin una al menos algo interesante.
Martineau
"Quiero usar for loop :-)" fue uno de los primeros comentarios de @pyfunc a la respuesta ahora eliminada
John Machin
1
@John Machin: No creo que se me pueda responsabilizar por no cumplir con las solicitudes en los comentarios de las respuestas eliminadas que no vi ni puedo ver. Sin embargo, a pesar de que mi segunda función no utiliza un forbucle, se hace de una manera responde a la pregunta real acerca de cómo raiseun ValueErrorcuando el personaje no se encuentra en la cadena - es decir, llamando a alguna otra cosa que lo hace por usted. También existe la posibilidad de que el OP pueda superar su for-fijación o lo que sea después de ver una forsolución sans- o familiarizarse con Python más adelante.
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
fuente
4
>>> response='bababa'
...  if "K" in response.text:
...     raise ValueError("Not found")
Kaushik Dey
fuente
1
Si bien este código puede responder a la pregunta, proporcionar un contexto adicional sobre cómo y / o por qué resuelve el problema mejoraría el valor de la respuesta a largo plazo.
Donald Duck