simbolos sentencias relacionales operadores numeros estructuras else ejemplos control comparar python coding-style if-statement

relacionales - sentencias en python



¿Estilizando condiciones de multilínea en declaraciones ''if''? (29)

"todos" y "cualquiera" son agradables para las muchas condiciones del mismo tipo de caso. PERO siempre evalúan todas las condiciones. Como se muestra en este ejemplo:

def c1(): print " Executed c1" return False def c2(): print " Executed c2" return False print "simple and (aborts early!)" if c1() and c2(): pass print print "all (executes all :( )" if all((c1(),c2())): pass print

A veces rompo largas condiciones en if está en varias líneas. La forma más obvia de hacer esto es:

if (cond1 == ''val1'' and cond2 == ''val2'' and cond3 == ''val3'' and cond4 == ''val4''): do_something

No es muy atractivo visualmente, porque la acción se combina con las condiciones. Sin embargo, es la forma natural de usar la sangría Python correcta de 4 espacios.

Por el momento estoy usando:

if ( cond1 == ''val1'' and cond2 == ''val2'' and cond3 == ''val3'' and cond4 == ''val4''): do_something

Pero esto no es muy bonito. :-)

¿Puedes recomendar una forma alternativa?


¿Qué pasa si solo insertamos una línea en blanco adicional entre la condición y el cuerpo y hacemos el resto de forma canónica?

if (cond1 == ''val1'' and cond2 == ''val2'' and cond3 == ''val3'' and cond4 == ''val4''): do_something

ps siempre uso tabulaciones, no espacios; No puedo afinar ...


(He modificado ligeramente los identificadores, ya que los nombres de ancho fijo no son representativos del código real, al menos no del código real con el que me encuentro, y desmienten la legibilidad de un ejemplo).

if (cond1 == "val1" and cond22 == "val2" and cond333 == "val3" and cond4444 == "val4"): do_something

Esto funciona bien para "y" y "o" (es importante que sean los primeros en la segunda línea), pero mucho menos para otras condiciones prolongadas. Afortunadamente, el primero parece ser el caso más común, mientras que el último suele ser fácilmente reescrito con una variable temporal. (Por lo general, no es difícil, pero puede ser difícil o mucho menos obvio / legible mantener el cortocircuito de "y" / "o" ​​al reescribir).

Desde que encontré esta pregunta de tu blog sobre C ++ , incluiré que mi estilo de C ++ es idéntico:

if (cond1 == "val1" and cond22 == "val2" and cond333 == "val3" and cond4444 == "val4") { do_something }


Agregando a lo que dijo @krawyoti ... Las condiciones duras huelen porque son difíciles de leer y de entender. El uso de una función o una variable hace que el código sea más claro. En Python, prefiero usar el espacio vertical, encerrar paréntesis y colocar los operadores lógicos al principio de cada línea para que las expresiones no parezcan "flotantes".

conditions_met = ( cond1 == ''val1'' and cond2 == ''val2'' and cond3 == ''val3'' and cond4 == ''val4'' ) if conditions_met: do_something

Si es necesario evaluar las condiciones más de una vez, como en un bucle while, entonces lo mejor es usar una función local.


Aquí hay otro enfoque:

cond_list = [''cond1 == "val1"'',''cond2=="val2"'',''cond3=="val3"'',''cond4=="val4"''] if all([eval(i) for i in cond_list]): do something

Esto también hace que sea fácil agregar otra condición fácilmente sin cambiar la declaración if simplemente agregando otra condición a la lista:

cond_list.append(''cond5=="val5"'')


Creo que la solución de @zkanda sería buena con un pequeño giro. Si tuviera sus condiciones y valores en sus propias listas respectivas, podría usar una comprensión de lista para hacer la comparación, lo que haría las cosas un poco más generales para agregar pares de condición / valor.

conditions = [1, 2, 3, 4] values = [1, 2, 3, 4] if all([c==v for c, v in zip(conditions, values)]): # do something

Si quisiera codificar una declaración como esta, la escribiría así para legibilidad:

if (condition1==value1) and (condition2==value2) and / (condition3==value3) and (condition4==value4):

Y solo para lanzar otra solución con un operador iand :

proceed = True for c, v in zip(conditions, values): proceed &= c==v if proceed: # do something


Empaque sus condiciones en una lista, luego haga algo. me gusta:

if False not in Conditions: do_something


Encuentro que cuando tengo largas condiciones, a menudo tengo un cuerpo de código corto. En ese caso, simplemente sangré el cuerpo, así:

if (cond1 == ''val1'' and cond2 == ''val2'' and cond3 == ''val3'' and cond4 == ''val4''): do_something


Esta es mi opinión muy personal: las condiciones largas son (en mi opinión) un olor a código que sugiere refactorizar en una función / método de retorno booleano. Por ejemplo:

def is_action__required(...): return (cond1 == ''val1'' and cond2 == ''val2'' and cond3 == ''val3'' and cond4 == ''val4'')

Ahora, si encuentro una manera de hacer que las condiciones de multilínea se vean bien, probablemente me satisfaría con tenerlas y me saltearía la refactorización.

Por otro lado, tenerlos perturbar mi sentido estético actúa como un incentivo para refactorizar.

Mi conclusión, por lo tanto, es que las condiciones de múltiples líneas deben verse feas y esto es un incentivo para evitarlas.


Esto es lo que hago, recuerde que "todos" y "cualquiera" aceptan un iterable, así que simplemente puse una condición larga en una lista y dejo que "todos" haga el trabajo.

condition = [cond1 == ''val1'', cond2 == ''val2'', cond3 == ''val3'', cond4 == ''val4''] if all(condition): do_something


Esto no mejora mucho pero ...

allCondsAreOK = (cond1 == ''val1'' and cond2 == ''val2'' and cond3 == ''val3'' and cond4 == ''val4'') if allCondsAreOK: do_something


He recurrido a lo siguiente en el caso degenerado en el que se trata simplemente de AND u OR.

if all( [cond1 == ''val1'', cond2 == ''val2'', cond3 == ''val3'', cond4 == ''val4''] ): if any( [cond1 == ''val1'', cond2 == ''val2'', cond3 == ''val3'', cond4 == ''val4''] ):

Afeita algunos caracteres y deja claro que no hay sutileza en la condición.


Llano y simple, también pasa cheques pep8:

if ( cond1 and cond2 ): print("Hello World!")

En los últimos tiempos, he estado prefiriendo all any funciones, ya que rara vez mezclo las comparaciones de Y y O esto funciona bien, y tiene la ventaja adicional de Failing Early con la comprensión de los generadores:

if all([ cond1, cond2, ]): print("Hello World!")

Solo recuerda pasar en un solo iterable! Pasar en N-argumentos no es correcto.

Nota: any es como muchos or comparaciones, all es como muchos and comparaciones.

Esto combina muy bien con las comprensiones del generador, por ejemplo:

# Check if every string in a list contains a substring: my_list = [ ''a substring is like a string'', ''another substring'' ] if all(''substring'' in item for item in my_list): print("Hello World!") # or if all( ''substring'' in item for item in my_list ): print("Hello World!")

Más sobre: comprensión de generador


Lo que suelo hacer es:

if (cond1 == ''val1'' and cond2 == ''val2'' and cond3 == ''val3'' and cond4 == ''val4'' ): do_something

De esta manera, el corsé y el colon de cierre marcan visualmente el final de nuestra condición.


Me sorprende no ver mi solución preferida.

if (cond1 == ''val1'' and cond2 == ''val2'' and cond3 == ''val3'' and cond4 == ''val4''): do_something

Ya que es una palabra clave, mi editor la resalta y se ve lo suficientemente diferente de do_something debajo de ella.


No necesitas usar 4 espacios en tu segunda línea condicional. Tal vez use:

if (cond1 == ''val1'' and cond2 == ''val2'' and cond3 == ''val3'' and cond4 == ''val4''): do_something

Además, no olvides que el espacio en blanco es más flexible de lo que piensas:

if ( cond1 == ''val1'' and cond2 == ''val2'' and cond3 == ''val3'' and cond4 == ''val4'' ): do_something if (cond1 == ''val1'' and cond2 == ''val2'' and cond3 == ''val3'' and cond4 == ''val4''): do_something

Sin embargo, ambos son bastante feos.

Tal vez pierda los corchetes (aunque la Guía de estilo desalienta esto)?

if cond1 == ''val1'' and cond2 == ''val2'' and / cond3 == ''val3'' and cond4 == ''val4'': do_something

Esto al menos te da alguna diferenciación.

O incluso:

if cond1 == ''val1'' and cond2 == ''val2'' and / cond3 == ''val3'' and / cond4 == ''val4'': do_something

Creo que prefiero:

if cond1 == ''val1'' and / cond2 == ''val2'' and / cond3 == ''val3'' and / cond4 == ''val4'': do_something

Aquí está la guía de estilo , que (desde 2010) recomienda usar corchetes.


Parece que vale la pena citar el PEP 0008 (guía de estilo oficial de Python), ya que comenta sobre este tema con una extensión modesta:

Cuando la parte condicional de una declaración if es lo suficientemente larga como para requerir que se escriba en varias líneas, vale la pena señalar que la combinación de una palabra clave de dos caracteres (es decir, if ) más un espacio, más un paréntesis de apertura crea un espacio natural. Sangría de 4 espacios para las siguientes líneas del condicional multilínea. Esto puede generar un conflicto visual con el conjunto de código sangrado anidado dentro de la sentencia if , que también se sangraría naturalmente en 4 espacios. Este PEP no toma una posición explícita sobre cómo (o si) distinguir más visualmente dichas líneas condicionales de la suite anidada dentro de la declaración if . Las opciones aceptables en esta situación incluyen, pero no se limitan a:

# No extra indentation. if (this_is_one_thing and that_is_another_thing): do_something() # Add a comment, which will provide some distinction in editors # supporting syntax highlighting. if (this_is_one_thing and that_is_another_thing): # Since both conditions are true, we can frobnicate. do_something() # Add some extra indentation on the conditional continuation line. if (this_is_one_thing and that_is_another_thing): do_something()

Tenga en cuenta el "no limitado a" en la cita anterior; además de los enfoques sugeridos en la guía de estilo, algunos de los sugeridos en otras respuestas a esta pregunta también son aceptables.


Personalmente, me gusta agregar un significado a las largas sentencias if. Tendría que buscar en el código para encontrar un ejemplo apropiado, pero aquí está el primer ejemplo que me viene a la mente: digamos que me encuentro con alguna lógica extraña donde quiero mostrar una página determinada dependiendo de muchas variables.

Inglés: "Si el usuario que ha iniciado sesión NO es un maestro administrador, sino que es solo un maestro regular, y no es un estudiante por sí mismo ..."

if not user.isAdmin() and user.isTeacher() and not user.isStudent(): doSomething()

Claro que esto puede verse bien, pero leer esas frases si es mucho trabajo. ¿Qué tal si asignamos la lógica a la etiqueta que tiene sentido. La "etiqueta" es en realidad el nombre de la variable:

displayTeacherPanel = not user.isAdmin() and user.isTeacher() and not user.isStudent() if displayTeacherPanel: showTeacherPanel()

Esto puede parecer una tontería, pero es posible que tenga otra condición en la que SOLO desee mostrar otro elemento si, y solo si, está mostrando el panel del profesor O si el usuario tiene acceso a ese otro panel específico de manera predeterminada:

if displayTeacherPanel or user.canSeeSpecialPanel(): showSpecialPanel()

Intente escribir la condición anterior sin usar variables para almacenar y etiquetar su lógica, y no solo termina con una declaración lógica muy complicada y difícil de leer, sino que también lo repitió. Si bien hay excepciones razonables, recuerde: no se repita (DRY).


Podrías dividirlo en dos líneas.

total = cond1 == ''val'' and cond2 == ''val2'' and cond3 == ''val3'' and cond4 == val4 if total: do_something()

O incluso agregar en una condición a la vez. De esa manera, al menos separa el desorden del if .


Prefiero este estilo cuando tengo una condición terriblemente grande:

if ( expr1 and (expr2 or expr3) and hasattr(thingy1, ''__eq__'') or status=="HappyTimes" ): do_stuff() else: do_other_stuff()


Sé que este hilo es antiguo, pero tengo un código de Python 2.7 y PyCharm (4.5) aún se queja sobre este caso:

if foo is not None: if (cond1 == ''val1'' and cond2 == ''val2'' and cond3 == ''val3'' and cond4 == ''val4''): # some comment about do_something do_something

Incluso con la advertencia PEP8 "línea con sangría visual con la misma sangría que la siguiente línea lógica", ¿el código real está completamente bien? ¿No es "una sangría excesiva?"

... hay veces en las que desearía que Python hubiera mordido la bala y se hubiera ido con llaves. Me pregunto cuántos errores se han introducido accidentalmente a lo largo de los años debido a una sangría accidental ...


Sólo algunas otras ideas aleatorias por el bien de la integridad. Si trabajan para ti, úsalos. De lo contrario, probablemente sea mejor que intentes algo más.

También puedes hacer esto con un diccionario:

>>> x = {''cond1'' : ''val1'', ''cond2'' : ''val2''} >>> y = {''cond1'' : ''val1'', ''cond2'' : ''val2''} >>> x == y True

Esta opción es más complicada, pero también puede resultarle útil:

class Klass(object): def __init__(self, some_vars): #initialize conditions here def __nonzero__(self): return (self.cond1 == ''val1'' and self.cond2 == ''val2'' and self.cond3 == ''val3'' and self.cond4 == ''val4'') foo = Klass() if foo: print "foo is true!" else: print "foo is false!"

No sé si eso funciona para ti, pero es otra opción a considerar. Aquí hay una manera más:

class Klass(object): def __init__(self): #initialize conditions here def __eq__(self): return (self.cond1 == ''val1'' and self.cond2 == ''val2'' and self.cond3 == ''val3'' and self.cond4 == ''val4'') x = Klass(some_values) y = Klass(some_other_values) if x == y: print ''x == y'' else: print ''x!=y''

Los dos últimos no los he probado, pero los conceptos deberían ser suficientes para ponerte en marcha si eso es lo que quieres.

(Y para que quede constancia, si esto es solo una vez, probablemente esté mejor usando el método que presentó al principio. Si está haciendo la comparación en muchos lugares, estos métodos pueden mejorar la legibilidad lo suficiente para que no te sientes tan mal por el hecho de que son una especie de hacky.)


Si nuestra condición if & an else tiene que ejecutar varias sentencias dentro de ella, podemos escribirla a continuación. Cada vez que tenemos otro ejemplo con una declaración dentro de ella.

Gracias funciona para mí.

#!/usr/bin/python import sys numberOfArgument =len(sys.argv) weblogic_username ='''' weblogic_password = '''' weblogic_admin_server_host ='''' weblogic_admin_server_port ='''' if numberOfArgument == 5: weblogic_username = sys.argv[1] weblogic_password = sys.argv[2] weblogic_admin_server_host =sys.argv[3] weblogic_admin_server_port=sys.argv[4] elif numberOfArgument <5: print " weblogic UserName, weblogic Password and weblogic host details are Mandatory like, defalutUser, passwordForDefaultUser, t3s://server.domainname:7001 ." weblogic_username = raw_input("Enter Weblogic user Name") weblogic_password = raw_input(''Enter Weblogic user Password'') weblogic_admin_server_host = raw_input(''Enter Weblogic admin host '') weblogic_admin_server_port = raw_input(''Enter Weblogic admin port'') #enfelif #endIf


Suelo usar:

if ((cond1 == ''val1'' and cond2 == ''val2'' and cond3 == ''val3'' and cond4 == ''val4'')): do_something()


Sugiero mover la palabra clave and a la segunda línea y sangrar todas las líneas que contienen condiciones con dos espacios en lugar de cuatro:

if (cond1 == ''val1'' and cond2 == ''val2'' and cond3 == ''val3'' and cond4 == ''val4''): do_something

Así es exactamente como soluciono este problema en mi código. Tener una palabra clave como la primera palabra en la línea hace que la condición sea mucho más legible, y reducir el número de espacios distingue más la condición de la acción.


También he estado luchando para encontrar una manera decente de hacer esto, así que se me ocurrió una idea (no una bala de plata, ya que esto es principalmente una cuestión de gustos).

if bool(condition1 and condition2 and ... conditionN): foo() bar()

Encuentro algunos méritos en esta solución en comparación con otros que he visto, a saber, obtienes exactamente 4 espacios adicionales de sangría (bool), lo que permite que todas las condiciones se alineen verticalmente, y el cuerpo de la declaración if puede sangrarse en una manera clara (ish) Esto también mantiene los beneficios de la evaluación en corto circuito de operadores booleanos, pero, por supuesto, agrega la sobrecarga de una llamada de función que básicamente no hace nada. Podría argumentar (válidamente) que cualquier función que devuelva su argumento podría usarse aquí en lugar de bool, pero como dije, es solo una idea y, en última instancia, es una cuestión de gustos.

Lo suficientemente divertido, mientras escribía esto y pensaba en el "problema", se me ocurrió otra idea, que elimina la sobrecarga de una llamada de función. ¿Por qué no indicar que estamos por ingresar a una condición compleja utilizando pares de paréntesis adicionales? Decir, 2 más, para dar una bonita sangría de 2 espacios de las sub-condiciones relativas al cuerpo de la sentencia if. Ejemplo:

if (((foo and bar and frob and ninja_bear))): do_stuff()

Me gusta esto porque cuando lo miras, inmediatamente suena una campana en tu cabeza que dice "hey, ¡aquí está pasando algo complejo!" . Sí, sé que los paréntesis no ayudan a la legibilidad, pero estas condiciones deben aparecer lo suficientemente raras y, cuando aparezcan, tendrá que detenerse y leerlas con cuidado (porque son complejas ).

De todos modos, solo hay dos propuestas más que no he visto aquí. Espero que esto ayude a alguien :)


Todos los encuestados que también proporcionan condicionales múltiples para la sentencia if son tan feos como el problema presentado. No resuelves este problema haciendo lo mismo ..

Incluso la respuesta PEP 0008 es repulsiva.

Aquí hay un enfoque mucho más legible

condition = random.randint(0, 100) # to demonstrate anti_conditions = [42, 67, 12] if condition not in anti_conditions: pass

¿Quieres que me coma mis palabras? Convénceme que necesitas condicionales múltiples y literalmente imprimiré esto y lo comeré para tu diversión.


¡Alguien tiene que defender el uso del espacio en blanco vertical aquí! :)

if ( cond1 == val1 and cond2 == val2 and cond3 == val3 ): do_stuff()

Esto hace que cada condición sea claramente visible. También permite una expresión más limpia de condiciones más complejas:

if ( cond1 == val1 or ( cond2_1 == val2_1 and cond2_2 >= val2_2 and cond2_3 != bad2_3 ) ): do_more_stuff()

Sí, estamos cambiando un poco de bienes raíces verticales para mayor claridad. Bien vale la pena IMO.