En Perl, puedo hacer algo como esto para crear dinámicamente una matriz en función de algunas condiciones:
my @arr = ( $foo_defined ? 'foo' : (), $bar_defined ? 'bar' : (), $baz_defined ? 'baz' : (), );Esto crea una matriz de hasta 3 elementos en función de los valores de las variables. ¿Cuál sería la alternativa más cercana a esto en Python?
Una traducción literal cercana podría ser
arr = list(chain( ['foo'] if foo_defined else [], ['bar'] if bar_defined else [], ['baz'] if baz_defined else [], )) a if b else c es el equivalente Python de b ? a : c . chain concatena múltiples valores iterables en una sola secuencia, similar a cómo ( (), (), () ) construye una matriz que consta de elementos de matriz (en lugar de anidar las matrices). list convierte el objeto de la chain en una lista real.
Las diferentes semánticas de una matriz de Perl y una lista de Python dificultan hacer exactamente lo mismo con tanta concisión como lo hace Perl. Python carece de la capacidad de hacer que una expresión se evalúe como nada para simular el manejo de matrices de Perl en su ejemplo. (O dicho de otra manera, [ [], [], [] ] en Python crea una lista que contiene 3 listas vacías, en lugar de una sola lista vacía).
La respuesta de Patrick Artner aprovecha el hecho de que la comprensión de una lista puede incluir selectivamente valores de un iterable en la lista en construcción.
Una combinación de sus respuestas y las mías podría verse como
arr = [s for s in ['foo' if foo_defined else None, 'bar' if bar_defined else None, 'baz' if baz_defined else None] if s is not None]La diferencia, sin embargo, es que primero se construye una lista completa , luego se construye una segunda lista final a partir de la primera.
La respuesta de Rolv Apneseth prescinde de una sola expresión, construye el resultado a partir de una lista inicialmente vacía y agrega valores condicionalmente, un elemento a la vez. Es conciso, pero la simulación de modificadores de declaraciones al estilo de Perl no es realmente idiomática en Python. En su lugar, uno simplemente usaría declaraciones if :
arr = [] if foo_defined: arr.append("foo") if bar_defined: arr.append("bar") if baz_defined: arr.append("baz")La comprensión de lista condicional puede hacerlo:
defines = [True, False, True] data = ["foo", "bar", "baz"] result = [d for defined,d in zip(defines,data) if defined] print(result)Llegar
['foo', 'baz'] zip() necesita listas de la misma longitud: use iterools.zip_longest si necesita más libertad de acción o valores predeterminados.
Si entendí bien (no sé nada de Perl, me temo), tal vez algo como esto:
foo_defined = True bar_defined = False baz_defined = True arr = [] foo_defined and arr.append("foo") bar_defined and arr.append("bar") baz_defined and arr.append("baz")Producción
> print(arr) ['foo', 'baz']