Estoy seguro de que hay una manera más simple de hacer esto que simplemente no se me ocurre.
Estoy llamando a un montón de métodos que devuelven una lista. La lista puede estar vacía. Si la lista no está vacía, quiero devolver el primer elemento; de lo contrario, quiero devolver ninguno. Este código funciona:
my_list = get_list()
if len(my_list) > 0: return my_list[0]
return None
Me parece que debería haber un lenguaje simple de una línea para hacer esto, pero por mi vida no puedo pensar en eso. ¿Esta ahí?
Editar:
La razón por la que estoy buscando una expresión de una línea aquí no es que me guste el código increíblemente conciso, sino porque tengo que escribir mucho código como este:
x = get_first_list()
if x:
# do something with x[0]
# inevitably forget the [0] part, and have a bug to fix
y = get_second_list()
if y:
# do something with y[0]
# inevitably forget the [0] part AGAIN, and have another bug to fix
Lo que me gustaría hacer sin duda se puede lograr con una función (y probablemente lo será):
def first_item(list_or_none):
if list_or_none: return list_or_none[0]
x = first_item(get_first_list())
if x:
# do something with x
y = first_item(get_second_list())
if y:
# do something with y
Publiqué la pregunta porque con frecuencia me sorprende lo que pueden hacer las expresiones simples en Python, y pensé que escribir una función era algo tonto si había una expresión simple que pudiera hacer el truco. Pero al ver estas respuestas, parece que una función es la solución simple.
fuente

next(iter(your_list), None)lugar defirst_item(your_list)asumiryour_listque no lo esNone(get_first_list()yget_second_list()siempre debe devolver un iterable).next(iter(your_list)), ya que si proporciona un segundo argumento paraiter, le está diciendo que el primer argumento es invocable.Noneaquí está el segundo parámetro paranext(), noiter().next()devuelve su segundo parámetro si se proporciona en lugar de aumentarStopIterationsiyour_listestá vacío.Respuestas:
Python 2.6+
Si
your_listpuede serNone:Python 2.4
Ejemplo:
Otra opción es alinear la función anterior:
Para evitar que
breakpuedas escribir:Dónde:
fuente
""en la lista, se descarta y se reemplaza por una lista vacía[]. Si tienes un 0, también reemplazado por[]. Si tienesFalseallí, también reemplazado. Etc. Puede salirse con la suya en un caso específico, pero este es un mal hábito para desarrollar.bool(lst)nos dice silen(lst) > 0no nos dice nada sobre qué elementoslstcontiene,bool([False]) == True;por ejemplo, por lo tanto , la expresión[False] or []regresa[False], lo mismo es para[0] or []que regrese[0].yield_first()para evitar labreakdeclaración.La mejor manera es esta:
También puede hacerlo en una línea, pero es mucho más difícil de leer para el programador:
fuente
next(iter(your_list), None)next(iter(your_list))es suficienteNonecomo OP pregunta. Proveedores:next(iter([])).Eso debería funcionar.
Por cierto, no utilicé la variable
list, porque eso sobrescribe lalist()función incorporada .Editar: tuve una versión un poco más simple, pero incorrecta aquí anteriormente.
fuente
La forma más idiomática de Python es usar next () en un iterador ya que la lista es iterable . justo como lo que @JFSebastian puso en el comentario el 13 de diciembre de 2011.
next(iter(the_list), None)Esto devuelve Ninguno sithe_listestá vacío. ver siguiente () Python 2.6+o si sabes con certeza
the_listque no está vacío:iter(the_list).next()ver iterator.next () Python 2.2+fuente
return l[0] if l else Nonesi la lista fuera libcomp. Cuando la lista es en realidad un genexpr esto es aún mejor, ya que no tiene que construir toda la lista como ennext(iter(x for x in range(10) if x % 2 == 0), None)the_listque no está vacío, escribiríathe_list[0].Si te encuentras tratando de extraer lo primero (o Ninguno) de una lista de comprensión, puedes cambiar a un generador para hacerlo como:
Pro: funciona si bla no es indexable Con: es una sintaxis desconocida. Sin embargo, es útil al piratear y filtrar cosas en ipython.
fuente
La solución del OP está casi allí, solo hay algunas cosas para hacerlo más Pythonic.
Por un lado, no es necesario obtener la longitud de la lista. Las listas vacías en Python evalúan a False en una comprobación if. Solo di
Además, es una muy mala idea asignar variables que se superponen con palabras reservadas. "lista" es una palabra reservada en Python.
Así que cambiemos eso a
Un punto realmente importante que muchas de las soluciones aquí pasan por alto es que todas las funciones / métodos de Python no devuelven ninguno de forma predeterminada . Pruebe lo siguiente a continuación.
A menos que necesite devolver None para terminar una función antes, no es necesario devolver None explícitamente. Muy sucintamente, solo devuelva la primera entrada, en caso de que exista.
Y finalmente, tal vez esto estaba implícito, pero solo para ser explícito (porque explícito es mejor que implícito ), no debería hacer que su función obtenga la lista de otra función; solo pásalo como parámetro. Entonces, el resultado final sería
Como dije, el OP estaba casi allí, y solo unos pocos toques le dan el sabor Python que estás buscando.
fuente
get_first_itemdebería aceptar undefaultparámetro (comodict.get) que por defecto sea Ninguno. Por lo tanto, la interfaz de la función comunica explícitamente lo que sucede simy_listestá vacío.fuente
Hablando francamente, no creo que haya una mejor expresión idiomática: la tuya es clara y concisa, no hay necesidad de nada "mejor". Tal vez, pero esto es realmente una cuestión de gusto, usted podría cambiar
if len(list) > 0:conif list:- una lista vacía siempre evaluará a falso.En una nota relacionada, Python no es Perl (¡sin juego de palabras!), No tiene que obtener el código más genial posible.
En realidad, el peor código que he visto en Python, también fue genial :-) y completamente imposible de mantener.
Por cierto, la mayor parte de la solución que he visto aquí no tiene en cuenta cuando la lista [0] se evalúa como False (por ejemplo, cadena vacía o cero); en este caso, todos devuelven None y no el elemento correcto.
fuente
if lst:lugar de hacerloif len(lst) > 0:. Además, no use palabras clave de Python como nombres de variables; termina en lágrimas. Es común usarLolstcomo nombre de variable para alguna lista. Estoy seguro de que en este caso no quiso sugerir que se usara realmentelistcomo un nombre de variable, solo quiso decir "alguna lista". Y, +1 para "cuando lst [0] se evalúa como False".El enfoque más pitónico es lo que demostró la respuesta más votada, y fue lo primero que se me ocurrió cuando leí la pregunta. Aquí se explica cómo usarlo, primero si la lista posiblemente vacía se pasa a una función:
Y si la lista se devuelve desde una
get_listfunción:Otras formas demostradas para hacer esto aquí, con explicaciones
forCuando comencé a pensar en formas inteligentes de hacer esto, esta es la segunda cosa que pensé:
Esto supone que la función termina aquí, devolviendo implícitamente
Nonesiget_listdevuelve una lista vacía. El siguiente código explícito es exactamente equivalente:if some_listTambién se propuso lo siguiente (corrigí el nombre de variable incorrecto) que también usa lo implícito
None. Esto sería preferible a lo anterior, ya que utiliza la verificación lógica en lugar de una iteración que puede no ocurrir. Esto debería ser más fácil de entender de inmediato lo que está sucediendo. Pero si estamos escribiendo para facilitar la lectura y el mantenimiento, también deberíamos agregar el explícitoreturn Noneal final:cortar
or [None]y seleccionar el índice ceroEsta también está en la respuesta más votada:
El segmento no es necesario y crea una lista adicional de un elemento en la memoria. Lo siguiente debería ser más eficiente. Para explicar,
ordevuelve el segundo elemento si el primero estáFalseen un contexto booleano, por lo que siget_listdevuelve una lista vacía, la expresión contenida entre paréntesis devolverá una lista con 'Ninguno', a la que luego accederá el0índice:El siguiente usa el hecho de que devuelve el segundo elemento si el primero está
Trueen un contexto booleano, y dado que hace referencia a my_list dos veces, no es mejor que la expresión ternaria (y técnicamente no es una línea):nextLuego tenemos el siguiente uso inteligente del builtin
nextyiterPara explicar,
iterdevuelve un iterador con un.nextmétodo. (.__next__En Python 3.) A continuación, la orden internanextllamadas que.nextel método, y si el iterador está agotado, devuelve el valor por defecto que damos,None.expresión ternaria redundante (
a if b else c) y vuelta en círculoSe propuso lo siguiente, pero sería preferible lo inverso, ya que la lógica generalmente se entiende mejor en lo positivo que en lo negativo. Como
get_listse llama dos veces, a menos que el resultado se memorice de alguna manera, esto funcionaría mal:El mejor inverso:
Aún mejor, use una variable local para que
get_listsolo se llame una vez, y primero tendrá la solución Pythonic recomendada:fuente
En cuanto a los modismos, hay una receta itertools llamada
nth.De las recetas de itertools:
Si desea frases sencillas, considere instalar una biblioteca que implemente esta receta para usted, por ejemplo
more_itertools:Hay otra herramienta disponible que solo devuelve el primer elemento, llamado
more_itertools.first.Estas herramientas de iteración escalan genéricamente para cualquier iterable, no solo para listas.
fuente
my_list[0] if len(my_list) else Nonefuente
lensin ninguna razón. Si fuera a eliminarlo, el código anterior haría lo mismo.Por curiosidad, corrí tiempos en dos de las soluciones. La solución que utiliza una declaración de devolución para finalizar prematuramente un bucle for es un poco más costosa en mi máquina con Python 2.5.1, sospecho que esto tiene que ver con la configuración del iterable.
Estos son los horarios que obtuve:
listas_vacías: index_first_item: 0.748353 segundos 0,741086 segundos 0,741191 segundos 0,743543 segundos promedio return_first_item: 0,785511 segundos 0.822178 segundos 0,782846 segundos 0,796845 segundos promedio listas_completas: index_first_item: 0,762618 segundos 0,788040 segundos 0,786849 segundos 0,779169 segundos promedio return_first_item: 0,802735 segundos 0.878706 segundos 0,808781 segundos 0,830074 segundos promedio listas_mezcladas: index_first_item: 0.791129 segundos 0,743526 segundos 0.744441 segundos 0,759699 segundos promedio return_first_item: 0.784801 segundos 0,785146 segundos 0.840193 segundos 0,803380 segundos promediofuente
fuente
if len(a) > 0:pero esto se considera un buen estilo. Tenga en cuenta lo bien que esto expresa el problema: "intente extraer el encabezado de una lista, y si eso no funciona, vuelvaNone". Busque en Google "EAFP" o busque aquí: python.net/~goodger/projects/pycon/2007/idiomatic/…Por cierto: retrabajaría el flujo general de su programa en algo como esto:
(Evitar la repetición siempre que sea posible)
fuente
Qué tal esto:
(my_list and my_list[0]) or NoneNota: Esto debería funcionar bien para las listas de objetos, pero podría devolver una respuesta incorrecta en caso de una lista de números o cadenas según los comentarios a continuación.
fuente
([0,1] and 0) or None!(['','A'] and '') or None.my_list[0]se evalúa comoFalse, el resultado debería serNone.my_list[0] if len(my_list) else NoneNo estoy seguro de cuán pitónico es esto, pero hasta que haya una primera función en la biblioteca, incluyo esto en la fuente:
Es solo una línea (se ajusta al negro) y evita dependencias.
fuente
Usando el truco o:
fuente
Probablemente no sea la solución más rápida, pero nadie mencionó esta opción:
si
get_list()puede regresarNonepuede usar:Ventajas:
-una línea
-solo llamas
get_list()una vez-fácil de comprender
fuente
Mi caso de uso fue solo para establecer el valor de una variable local.
Personalmente encontré la prueba y excepto el limpiador de estilo para leer
que cortar una lista.
fuente
Varias personas han sugerido hacer algo como esto:
Eso funciona en muchos casos, pero solo funcionará si la lista [0] no es igual a 0, Falso o una cadena vacía. Si list [0] es 0, False o una cadena vacía, el método devolverá None de forma incorrecta.
fuente
Puedes usar el método de extracción . En otras palabras, extraiga ese código en un método que luego llamaría.
No trataría de comprimirlo mucho más, los revestimientos parecen más difíciles de leer que la versión detallada. Y si usa el método de extracción, es un trazador de líneas;)
fuente
fuente
no es la pitón idiomática equivalente a operadores ternarios de estilo C
es decir.
fuente