A veces rompo condiciones largas en if
s 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 usando la sangría correcta de Python 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. :-)
¿Me puede recomendar una forma alternativa?
python
coding-style
if-statement
Eli Bendersky
fuente
fuente
pep8
criterios del paquete. El problemapep8
del paquete # 126 se trata de arreglar el paquete para seguir estrictamente la especificación PEP8. La discusión sobre el tema incluye algunas sugerencias de estilo que también se ven aquí.Respuestas:
No necesita usar 4 espacios en su segunda línea condicional. Tal vez use:
Además, no olvide que el espacio en blanco es más flexible de lo que podría pensar:
Sin embargo, ambos son bastante feos.
¿Quizás perder los corchetes ( sin embargo, la Guía de estilo desalienta esto)?
Esto al menos te da alguna diferenciación.
O incluso:
Creo que prefiero:
Aquí está la Guía de estilo , que (desde 2010) recomienda usar corchetes.
fuente
and
yif
también.He recurrido a lo siguiente en el caso degenerado en el que se trata simplemente de AND u OR.
Afeita algunos caracteres y deja en claro que no hay sutileza en la condición.
fuente
if destroy_world and DestroyTheWorld() == world_is_destroyed: ...
. Genial, ahora acabas de destruir el mundo por accidente. ¿COMO PUDISTE?¡Alguien tiene que defender el uso del espacio en blanco vertical aquí! :)
Esto hace que cada condición sea claramente visible. También permite una expresión más limpia de condiciones más complejas:
Sí, estamos intercambiando un poco de bienes raíces verticales por claridad. Vale la pena en mi opinión.
fuente
and
, así comoor
) es después del operador, no antes.PEP8
sino que hace que sea más difícil determinar la operación lógica con la que se está encadenando. Rechazaría esto si llegara a mi escritorio a través de la revisión de código.Prefiero este estilo cuando tengo una condición si terriblemente grande:
fuente
and
yor
al comienzo de la línea viola PEP 0008 , que establece que "el lugar preferido para romper un operador binario es después del operador, no antes de él". . Sin embargo, me gusta tener el corchete de cierre y los dos puntos en su propia línea para separar la condición if del cuerpo (y es perfectamente posible hacerlo mientras se mantienen los operadores booleanos al final de la línea para cumplir con PEP-0008).For decades the recommended style was to break after binary operators. But this can hurt readability in two ways
...In Python code, it is permissible to break before or after a binary operator, as long as the convention is consistent locally. For new code Knuth's style is suggested.
(el estilo de Knuth es comenzar la línea con el operador).Aquí está 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:
Ahora, si encuentro una manera de hacer que las condiciones de varias líneas se vean bien, probablemente me contentaría con tenerlas y omitir la refactorización.
Por otro lado, hacer que perturben mi sentido estético actúa como un incentivo para la refactorización.
Mi conclusión, por lo tanto, es que las condiciones de varias líneas deben verse feas y esto es un incentivo para evitarlas.
fuente
Esto no mejora mucho pero ...
fuente
Sugiero mover la
and
palabra clave a la segunda línea y sangrar todas las líneas que contienen condiciones con dos espacios en lugar de cuatro:Así es exactamente como resuelvo 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 la reducción del número de espacios distingue aún más la condición de la acción.
fuente
Parece que vale la pena citar PEP 0008 (guía de estilo oficial de Python), ya que comenta sobre este tema con modesta extensión:
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.
fuente
Esto es lo que hago, recuerde que "todos" y "cualquiera" aceptan un iterable, así que solo pongo una condición larga en una lista y dejo que "todos" hagan el trabajo.
fuente
Me sorprende no ver mi solución preferida,
Como
and
es una palabra clave, mi editor la resalta y se ve lo suficientemente diferente del do_something debajo de ella.fuente
Además de lo que dijo @krawyoti ... Las condiciones largas huelen porque son difíciles de leer y difíciles de entender. El uso de una función o una variable aclara el código. En Python, prefiero usar el espacio vertical, encerrar paréntesis y colocar los operadores lógicos al comienzo de cada línea para que las expresiones no se vean como "flotantes".
Si las condiciones deben evaluarse más de una vez, como en un
while
bucle, lo mejor es usar una función local.fuente
Personalmente, me gusta agregar significado a las declaraciones if largas. Tendría que buscar a través del código para encontrar un ejemplo apropiado, pero este es el primer ejemplo que me viene a la mente: supongamos que me encuentro con una lógica peculiar donde quiero mostrar una determinada página dependiendo de muchas variables.
Inglés: "Si el usuario conectado NO es un maestro administrador, sino que es solo un maestro regular y no es un estudiante en sí mismo ..."
Claro que esto podría verse bien, pero leer esas declaraciones 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:
Esto puede parecer una tontería, pero es posible que tenga otra condición en la que SOLO quiera 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 forma predeterminada:
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 desordenada y difícil de leer, sino que también se repite. Si bien hay excepciones razonables, recuerde: no se repita (SECO).
fuente
"all" y "any" son agradables para las muchas condiciones del mismo tipo de caso. PERO siempre evalúan todas las condiciones. Como se muestra en este ejemplo:
fuente
all()
entonces, a menos que las envuelva en una lambda y utilice suf()
truco, todas serán evaluadas. En otras palabras, Aaron: Creo que Anders estaba tratando de hablar sobre las condiciones en general, usando callables como un ejemplo específico; pero su réplica se aplica solo a las funciones.(Modifiqué ligeramente los identificadores ya que los nombres de ancho fijo no son representativos del código real, al menos no el código real que encuentro, y creo que la legibilidad de un ejemplo).
Esto funciona bien para "y" y "o" (es importante que estén primero en la segunda línea), pero mucho menos para otras condiciones largas. Afortunadamente, el primero parece ser el caso más común, mientras que el segundo a menudo se reescribe fácilmente con una variable temporal. (Por lo general, no es difícil, pero puede ser difícil o mucho menos obvio / legible para preservar el cortocircuito de "y" / "o" al reescribir).
Como encontré esta pregunta en tu blog sobre C ++ , incluiré que mi estilo C ++ es idéntico:
fuente
Simple y simple, también pasa cheques pep8:
En los últimos tiempos he estado prefiriendo las funciones
all
yany
, ya que rara vez mezclo las comparaciones And and Or, esto funciona bien y tiene la ventaja adicional de Failing Early con la comprensión de los generadores:¡Solo recuerda pasar en un solo iterable! Pasar N-argumentos no es correcto.
Nota:
any
es como muchasor
comparaciones,all
es como muchasand
comparaciones.Esto combina muy bien con las comprensiones del generador, por ejemplo:
Más sobre: comprensión del generador
fuente
¿Qué sucede si solo insertamos una línea en blanco adicional entre la condición y el cuerpo y hacemos el resto de forma canónica?
ps Siempre uso pestañas, no espacios; No puedo afinar ...
fuente
and
yor
deberían comenzar en la siguiente líneaLo que suelo hacer es:
De esta manera, el corsé de cierre y el colon marcan visualmente el final de nuestra condición.
fuente
and
oor
.Todos los encuestados que también proporcionan condiciones múltiples para la declaración if son tan feos como el problema presentado. No resuelve este problema haciendo lo mismo ...
Incluso la respuesta PEP 0008 es repulsiva.
Aquí hay un enfoque mucho más legible
¿Quieres que me coma mis palabras? Convénceme de que necesitas múltiples condicionales y literalmente imprimiré esto y me lo comeré para tu diversión.
fuente
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 la lista para hacer la comparación, lo que haría las cosas un poco más generales para agregar pares de condición / valor.
Si quisiera codificar una declaración como esta, la escribiría así para que sea legible:
Y solo para lanzar otra solución con un
iand
operador :fuente
all(map(eq, have, expected))
. (confrom operator import eq
)Solo algunas otras ideas aleatorias para completar. Si funcionan para ti, úsalos. De lo contrario, probablemente sea mejor que intentes otra cosa.
También puedes hacer esto con un diccionario:
Esta opción es más complicada, pero también puede resultarle útil:
No sé si eso funciona para usted, pero es otra opción a considerar. Aquí hay una forma más:
Los dos últimos no los he probado, pero los conceptos deberían ser suficientes para ponerlo en marcha si eso es lo que desea.
(Y para que conste, si esto es solo una vez, probablemente sea mejor que uses el método que presentaste al principio. Si estás haciendo la comparación en muchos lugares, estos métodos pueden mejorar la legibilidad lo suficiente como para hacer no te sientes tan mal por el hecho de que son un poco hacky).
fuente
He estado luchando por encontrar una forma decente de hacer esto también, así que se me ocurrió una idea (no una bala de plata, ya que esto es principalmente una cuestión de gustos).
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), permitiendo 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 de cortocircuito de los operadores booleanos, pero, por supuesto, agrega la sobrecarga de una llamada de función que básicamente no hace nada. Se 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 cuestión de gustos.
Curiosamente, 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 a punto de entrar en una condición compleja mediante el uso de pares de paréntesis adicionales? Digamos 2 más para dar una buena sangría de 2 espacios de las subcondiciones relativas al cuerpo de la declaración if. Ejemplo:
Me gusta esto porque cuando lo miras, inmediatamente suena una campana en tu cabeza que dice "¡Oye, hay algo complejo aquí!" . Sí, sé que los paréntesis no ayudan a la legibilidad, pero estas condiciones deberían aparecer raramente, y cuando aparezcan, tendrás que detenerte y leerlas con cuidado de todos modos (porque son complejas ).
De todos modos, solo dos propuestas más que no he visto aquí. Espero que esto ayude a alguien :)
fuente
Podrías dividirlo en dos líneas.
O incluso agregar una condición a la vez. De esa manera, al menos separa el desorden del
if
.fuente
Sé que este hilo es antiguo, pero tengo un código Python 2.7 y PyCharm (4.5) todavía se queja de este caso:
Incluso con la advertencia PEP8 "línea visualmente sangrada con la misma sangría que la siguiente línea lógica", ¿el código real está completamente bien? No es "sobre-sangría?"
... hay veces 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 indentación accidental ...
fuente
Empaque sus condiciones en una lista, luego haga algo. me gusta:
fuente
Encuentro que cuando tengo condiciones largas, a menudo tengo un cuerpo de código corto. En ese caso, solo sangro dos veces el cuerpo, por lo tanto:
fuente
o si esto es más claro:
No hay ninguna razón por la que la sangría deba ser un múltiplo de 4 en este caso, por ejemplo, consulte "Alineado con delimitador de apertura":
http://google-styleguide.googlecode.com/svn/trunk/pyguide.html?showone=Indentation#Indentation
fuente
Aquí hay otro enfoque:
Esto también hace que sea fácil agregar otra condición fácilmente sin cambiar la instrucción if simplemente agregando otra condición a la lista:
fuente
Usualmente uso:
fuente
si nuestra condición if & an else tiene que ejecutar varias instrucciones dentro de ella, entonces podemos escribir como a continuación. Cada vez que tenemos un ejemplo if else con una declaración dentro de ella.
Gracias funciona para mi.
fuente
Disculpe mi novato, pero sucede que no estoy tan bien informado sobre #Python como cualquiera de ustedes aquí, pero sucede que he encontrado algo similar al escribir mis propios objetos en un modelado 3D BIM, por lo que adaptaré mi algoritmo a el de python.
El problema que encuentro aquí es de doble cara:
Para evitar todos estos problemas, su script debe ser así
Ventajas de este método:
El guión es legible.
La secuencia de comandos se puede mantener fácilmente.
Espero que les ayude a todos
fuente