Tengo el código que se ve algo como esto:

thing_index = thing_list.index(thing)
otherfunction(thing_list, thing_index)

aceptar de manera simplificada, pero usted consigue la idea. Ahora thing en realidad no podría estar en la lista, en cuyo caso quiero pasar a -1 como thing_index. En otros idiomas, esto es lo que usted esperaría index() para volver si no puede encontrar el elemento. De hecho, se lanza una ValueError.

Yo podría hacer esto:

try:
    thing_index = thing_list.index(thing)
except ValueError:
    thing_index = -1
otherfunction(thing_list, thing_index)

Pero esto se siente sucio, además de que no sé si ValueError podría ser planteada por alguna otra razón. Se me ocurrió la siguiente solución basada en el generador de funciones, pero me parece un poco complejo:

thing_index = ( [(i for i in xrange(len(thing_list)) if thing_list[i]==thing)] or [-1] )[0]

Hay un limpiador de manera de lograr lo mismo? Supongamos que la lista no está ordenada.

  • s/catch/excepto/ :o)
  • «…en cuyo caso quiero pasar a -1 como thing_index.» – Este es definitivamente de la onu-Python. Pasando una (sin sentido) el valor del testigo en el caso de que una operación no tiene éxito, no es bien visto – las excepciones son en realidad la forma correcta de aquí. Especialmente desde thing_list[-1] es una expresión válida, es decir, la última entrada en la lista.
  • facepalm…spot java programador 😛
  • hay str.find método que hace exactamente eso: devuelve -1 cuando la aguja no se encuentra en el sujeto.
  • Ninguno de ellos sería mejor…y esto sería análogo a dict[clave] vs dict.get[clave]
  • Hm, muy interesante. Voy a tener que ver esto con más detalle. str.index() lanza una excepción si la cadena de búsqueda no se encuentra.

InformationsquelleAutor Draemon | 2010-01-25

12 Comentarios

  1. 56

    No hay nada «sucio» sobre el uso de try-a excepción de la cláusula. Este es el python el camino. ValueError serán levantados por el .index único método, porque es el único código que tienes ahí!

    Para responder al comentario:

    En Python, más fácil pedir perdón que para obtener el permiso filosofía está bien establecido, y no index no se plantean este tipo de error para cualquier otro problema. No se que puedo pensar.

    • Seguramente las excepciones son para casos excepcionales, y esto no es nada de eso. Yo no tendría un problema si la excepción fue más específico que ValueError.
    • Sé que sólo puede ser arrojada desde que método, pero se garantiza que solo podrá ser lanzado para que la razón? No se que puedo pensar en otra razón índice de fallar..pero luego no son excepciones exactamente por aquellas cosas que no pueden pensar?
    • Es por eso que se verifica sólo para ValueError y no cualquier forma de excepción.
    • No {}.get(index, '') más python? Por no hablar de más corta a más legible.
    • no está definido para las listas. No está claro lo que el diccionario tiene que ver con esta cuestión.
    • Yo uso dict[clave] cuando espero que la clave para existir y dict.get(clave) cuando no estoy seguro, y yo soy en busca de algo equivalente aquí. Volviendo None en lugar de -1 estaría bien, pero como te comento a ti mismo, str.find() devuelve -1 entonces ¿por qué no hay lista.find() que hace lo mismo? Yo no voy a comprar el «python» argumento
    • bien str.find es un rudimento. No hay un equivalente integrado, el código que tienes es 100% equivalente a lo que find sería como si hubiera sido escrito en Python.
    • Pero el punto es que la mayoría de python solución es el uso de solo try/except y no el -1 valor de centinela en todo. I. E. se debe volver a escribir otherfunction. Por otro lado, si no está roto, …
    • podría ser un código de terceros, para ser honesto.
    • No entiendo por qué ValueError sólo sería planteada por la index() método sólo. Me refiero a que si has tenido somelist.index(somefun(somedata)) usted no sabe si somefun no elevar ValueError en algún lugar. Todo esto EFTP cosas que en realidad no tiene sentido en mucho de los casos

  2. 42
    thing_index = thing_list.index(elem) if elem in thing_list else -1

    Una línea. Simple. No hay excepciones.

    • Simple, sí, pero que va a hacer dos lineal búsquedas y mientras que el rendimiento no es un problema per se, que parece excesivo.
    • De acuerdo – que va a hacer 2 pases – pero es raro que de un mil-código de la línea de base de este va a ser el cuello de botella. 🙂 Uno siempre puede optar por un imperativo de la solución con for.
    • con lambd indexOf = lambda item,list_ : list_.index(item) if item in list_ else -1 # OR None
  3. 15

    La dict tipo de tiene un get función, donde si la clave no existe en el diccionario, el 2º argumento para get es el valor que debe devolver. Del mismo modo hay setdefault, que devuelve el valor en la dict si la clave existe, de lo contrario, se establece el valor de acuerdo a sus parámetros predeterminados y, a continuación, devuelve el valor predeterminado del parámetro.

    Se podría extender el list tipo para tener una getindexdefault método.

    class SuperDuperList(list):
        def getindexdefault(self, elem, default):
            try:
                thing_index = self.index(elem)
                return thing_index
            except ValueError:
                return default

    Que podría ser utilizado como:

    mylist = SuperDuperList([0,1,2])
    index = mylist.getindexdefault( 'asdf', -1 )
  4. 5

    No hay nada de malo con el código que utiliza ValueError. He aquí otra línea si desea evitar excepciones:

    thing_index = next((i for i, x in enumerate(thing_list) if x == thing), -1)
    • Es que en python 2.6? Yo sé que yo no lo mencionan, pero estoy usando 2.5. Esto es probablemente lo que me gustaría hacer en 2.6
    • Sí, next() existe una función en Python 2.6+ . Pero es fácil de implementar para 2.5, consulte next() implementación de la función de Python 2.5
  5. 3

    Este es un problema de la filosofía del lenguaje. En Java, por ejemplo, siempre ha existido una tradición de que las excepciones que en realidad debería ser usada sólo en «circunstancias excepcionales» que es cuando los errores han ocurrido, en lugar de para control de flujo. En un principio esto fue por motivos de rendimiento como Java las excepciones fueron lentos pero ahora esto se ha convertido en la aceptación de estilo.

    En contraste Python siempre ha utilizado excepciones para indicar el normal flujo del programa, como la elevación de un ValueError como los que estamos analizando aquí. No hay nada de «sucio» acerca de esto en Python estilo y hay muchos más de donde vino eso. Incluso un ejemplo más común es StopIteration excepción que es criado por un iterador del next() método para la señal de que no hay más valores.

    • En realidad, el JDK lanza camino demasiadas excepciones comprobadas, así que no estoy seguro de que la filosofía se aplica en realidad a Java. Yo no tengo un problema per se con StopIteration porque es claramente definidas por lo que la excepción de los medios. ValueError es sólo un poco demasiado genérico.
    • Me refería a la idea de que las excepciones no deben ser utilizados para el control de flujo: c2.com/cgi/wiki?DontUseExceptionsForFlowControl, no tanto el número de excepciones comprobadas que Java tiene que otra discusión: mindview.net/Etc/Discussions/CheckedExceptions
  6. 1

    Lo que acerca de esto:

    otherfunction(thing_collection, thing)

    Lugar de exponer algo tan dependiente de la implementación como un índice de la lista en función de la interfaz, el pase de la colección y de la cosa y dejar otherfunction lidiar con la «prueba de la pertenencia a» cuestiones. Si otherfunction está escrito para ser de tipo de colección-agnóstico, entonces es probable que empezar con:

    if thing in thing_collection:
        ... proceed with operation on thing

    que si thing_collection es una lista, tupla, establecer o dict.

    Esta es posiblemente la más clara que:

    if thing_index != MAGIC_VALUE_INDICATING_NOT_A_MEMBER:

    que es el código que ya tiene en otherfunction.

  7. 1

    Lo que acerca de como esta:

    temp_inx = (L + [x]).index(x) 
    inx = temp_inx if temp_inx < len(L) else -1
  8. 0

    Tengo el mismo problema con el «.index()» método de las listas. Yo no tengo ningún problema con el hecho de que se produce una excepción, pero estoy en desacuerdo con el hecho de que es un no-descriptivo ValueError. Yo podía entender si es que hubiera sido un IndexError, aunque.

    Puedo ver por qué volver «-1» sería un tema demasiado porque es un índice válido en Python. Pero siendo realistas, no nunca esperar una «.index()» método para devolver un número negativo.

    Aquí va un forro (ok, es algo largo de la línea …), pasa a través de la lista de exactamente una vez y regresa «Ninguno» si el elemento no se encuentra. Sería trivial de volver a escribir, volver -1, si así lo deseas.

    indexOf = lambda list, thing: \
                reduce(lambda acc, (idx, elem): \
                       idx if (acc is None) and elem == thing else acc, list, None)

    Cómo utilizar:

    >>> indexOf([1,2,3], 4)
    >>>
    >>> indexOf([1,2,3], 1)
    0
    >>>
  9. 0

    Si usted está haciendo esto a menudo es mejor a la estufa en una función auxiliar:

    def index_of(val, in_list):
        try:
            return in_list.index(val)
        except ValueError:
            return -1 
  10. 0

    Lo que acerca de este 😃 :

    li = [1,2,3,4,5] # create list 
    
    li = dict(zip(li,range(len(li)))) # convert List To Dict 
    print( li ) # {1: 0, 2: 1, 3: 2, 4:3 , 5: 4}
    li.get(20) # None 
    li.get(1)  # 0 
  11. -2

    No sé por qué usted debe pensar que es sucio… a causa de la excepción? si quieres un oneliner, aquí está:

    thing_index = thing_list.index(elem) if thing_list.count(elem) else -1

    pero te aconsejo en contra de su uso; creo que Ross Rogers es la mejor solución, utilizar un objeto para encapsular su desiderd comportamiento, no trate de empujar el lenguaje hasta sus límites en el costo de la legibilidad.

    • Sí, porque de la excepción. Tu código va a hacer dos lineal búsquedas ¿no es así? No es que el rendimiento que realmente importa aquí. El SuperDuperList solución es buena, pero parece excesivo en esta situación particular. Creo que voy a terminar sólo la captura de la excepción, pero quería ver si había un limpiador (para mi estética) en el camino.
    • bien va a encapsular el código en el find() función y será limpio 😉
    • Es curioso que mi respuesta tiene dos downvotes, mientras Emil Ivanov, mientras que semánticamente idénticas, es uno de los más upvoted. Probablemente esto sucede porque la mía es más lento, ya que he empleado count() en lugar de «en» operador… al menos un comentario diciendo que habría sido muy bien 🙂
  12. -2

    Te sugiero:

    if thing in thing_list:
      list_index = -1
    else:
      list_index = thing_list.index(thing)
    • El problema con esta solución es que «-1» es un índice válido en la lista (último índice; el primero de la final). Mejor manera de manejar esto sería devolver False en primera sucursal de su condición.

Dejar respuesta

Please enter your comment!
Please enter your name here