2010-04-15 14 views
18

¿Cuál es la forma más fácil de verificar si algo es una lista?Verificar si algo es una lista

Un método doSomething tiene los parámetros a y b. En el método, recorrerá la lista a y hará algo. Me gustaría saber si a es un list, antes de pasar, evitando un error o la desafortunada circunstancia de pasar una cadena y luego recuperar una letra de cada ciclo.

Esta pregunta debe haberse realizado antes; sin embargo, mis google me fallaron. Aclamaciones.

+7

Creo que la "forma de Python" sería permitir que las personas pasen cualquier cosa. Confíe en los codificadores usando su función. –

+7

"evitando así un error" ¿Cómo se verifica "evitar" el error? Todavía está mal. ¿Y qué pasa si alguien usa una tupla u otro objeto parecido a una lista que realmente funciona correctamente? ¿Por qué evitar que usen una clase de cosas como una lista en la que no pensabas? ¿Cómo esto "evita" el error? –

+0

La única vez que verifico tipos de argumentos es si deseo que mi función haga cosas diferentes para diferentes tipos, por ejemplo, enteros o cadenas. Pero incluso entonces, generalmente termino refacturando el código y eliminando los controles de tipo. Hoy en día, en realidad soy * más * propenso a escribir código que provoca 'ValueError' o algo así cuando la entrada es mala. A diferencia de C++, las excepciones son tus amigos. –

Respuesta

13

para permitir que más casos de uso, pero todavía tratar las series como escalares, no comprobar si hay un ser una lista, compruebe que no es una cadena:

if not isinstance(a, basestring): 
    ... 
+5

+1, me gusta esto porque hay muchas listas que no están bien, las cadenas (simples y unicode, de donde la 'basetring') son las ovejas negras y deberían ser las únicas. –

+1

El uso de este código indica que casi con certeza está haciendo algo mal. Si proporciona una API consistente, esto no debería ser necesario. Esto también puede violar las expectativas del usuario cuando los tipos se usan como están destinados, por ejemplo, cuando alguien usa un objeto que conceptualmente es una cadena, pero es una instancia de una clase diferente. –

4

Por lo general, se considera no un buen estilo para llevar a cabo el tipo de comprobación en Python, pero trate

if isinstance(a, list): 
    ... 

(Creo que también se puede comprobar si a.__iter__ hubiera).

+1

Tienes razón, no es un buen estilo el marcar a máquina. Verificar el método '__iter__' es igual de tonto: simplemente haz' para el elemento en un '. Si tienes una razón para sospechar que' a' no es iterable (¡travieso, travieso!), atrapa el 'TypeError'. –

+0

@Mike:' "12345" .__ iter__' -> AttributeError: objeto 'str' no tiene el atributo '__iter__', pero 'para x en" 12345 ": imprimir x' funciona. – kennytm

+1

Que debería ser * desalentador *, no * alentador *. La comprobación de' __iter__' solo funciona por detalle de implementación, no por alguna diferencia significativa, y no indica si un objeto es iterable o en cualquier método directo indica la información que está recibiendo sobre cadenas. Si un objeto usa el protocolo del iterador antiguo (llamando a índices secuenciales) o se implementa en C de una manera fea (tal que el método '__iter__' no está expuesto) como en este caso, el resultado parece poco intuitivo. –

7

I'd like a way to make sure a is a list, before looping through

Documente la función.

+1

Esta solución es la más poderosa, útil y sólida. –

+1

Tiene el beneficio adicional de que, si alguien te envía un correo electrónico y dice "hey, tu función hace algo extraño para las cadenas", automáticamente sabes que es un idiota. Ningún compilador puede hacer eso. – detly

+1

Pero a veces ya sabes que son idiotas, no pueden deshacerse de ellos, quieren que dejen de molestarte y se preguntan si hay algún código que puedas escribir para cortarlo de raíz. Es una esperanza vana; siempre hay más tontos creativos. Aquí es donde las personas obtienen ideas como lanzadores de misiles USB. –

9

Typechecking daña la generalidad, simplicidad y facilidad de mantenimiento de su código. Rara vez se usa en buenos programas idiomáticos de Python.

Hay dos razones principales por las que la gente quiere typecheck:

  1. Expedir errores si la persona que llama proporciona el tipo incorrecto.

    Esto no vale la pena su tiempo. Si el usuario proporciona un tipo incompatible para la operación que está realizando, ya se generará un error cuando se golpee la compatibilidad. Es preocupante que esto no ocurra inmediatamente, pero normalmente no lleva mucho tiempo y da como resultado un código que es más robusto, simple, eficiente y fácil de escribir.

    Muchas veces la gente insiste en esto con la esperanza de que puedan captar todas las tonterías que un usuario puede hacer. Si un usuario está dispuesto a hacer cosas arbitrariamente tontas, no hay nada que puedas hacer para detenerlo. Typechecking tiene principalmente el potencial de mantener a un usuario que ingresa con sus propios tipos que reemplazan a los reemplazados o cuando el usuario reconoce que su función en realidad debe ser polimórfica y proporciona algo diferente que puede aceptar la misma operación.

    Si tuviera un gran sistema en el que un montón de cosas creadas por muchas personas encajaran bien, usaría un sistema como zope.interface para probar que todo encaja bien.

  2. Para hacer cosas diferentes según los tipos de argumentos recibidos.

    Esto empeora el código porque su API es inconsistente. Una función o método debería hacer una cosa, no fundamentalmente cosas diferentes. Esto termina siendo una característica que generalmente no vale la pena apoyar.

    Un escenario común es tener un argumento que puede ser un foo o una lista de foos. Una solución más limpia es simplemente aceptar una lista de foos. Tu código es más simple y más consistente.Si se trata de un caso de uso importante e importante solo para tener un foo, puede considerar tener otro método/función de conveniencia que llame al que acepta una lista de foos y no pierde nada. Proporcionar la primera API no solo habría sido más complicado y menos consistente, sino que se rompería cuando los tipos no fueran los valores exactos esperados; en Python distinguimos entre los objetos en función de sus capacidades, no sus tipos reales. Casi siempre es mejor aceptar un iterable arbitrario o una secuencia en lugar de una lista y cualquier cosa que funcione como un foo en lugar de requerir un foo en particular.

Como puede ver, no creo que ninguno de los dos motivos sea lo suficientemente convincente como para realizar una comprobación en circunstancias normales.

Cuestiones relacionadas