python - sentencias - ¿Estilo de código para la sangría de la declaración ''if'' de varias líneas?
sentencias en python (9)
Esta pregunta ya tiene una respuesta aquí:
Al sangrar condiciones largas, normalmente haces algo como esto (en realidad, las sangrías de PyDev así):
if (collResv.repeatability is None or
collResv.somethingElse):
collResv.rejected = True
collResv.rejectCompletely()
Sin embargo, esto pone el bloque iniciado por la instrucción if en el mismo nivel de sangría que la última parte de la condición if, lo que hace que sea muy feo / difícil de leer, en mi opinión, ya que no se ve inmediatamente dónde comienza el bloque.
Algunos otros estilos en los que pensé:
if (collResv.repeatability is None or
collResv.somethingElse):
collResv.rejected = True
collResv.rejectCompletely()
Esto parece bastante inconsistente ya que la segunda línea está sangrada mucho más que la primera línea, pero es legible.
if (collResv.repeatability is None or
collResv.somethingElse):
collResv.rejected = True
collResv.rejectCompletely()
Esto también es más legible que el primer ejemplo, pero la sangría ya no es un múltiplo de 4 y además parece incorrecto ya que la segunda línea tiene menos sangría que el comienzo de la condición en la primera línea.
Por lo tanto, mi pregunta principal es: ¿Hay un estilo de sangría sugerido para casos como el que no requieren líneas excesivamente largas (es decir, una condición de línea única)? Si no, ¿qué prefieres para casos como ese?
A menudo trabajo alrededor de este problema calculando la condición en una declaración propia:
condition = (collResv.repeatability is None or
collResv.somethingElse)
if condition:
collResv.rejected = True
collResv.rejectCompletely()
Sin embargo, para una condición aún relativamente corta como en su ejemplo específico, buscaría la solución de nosklo ; la declaración adicional utilizada aquí es más adecuada para expresiones condicionales incluso más largas.
En tal caso, simplemente lo haría:
if (collResv.repeatability is None or
collResv.somethingElse):
# do:
collResv.rejected = True
collResv.rejectCompletely()
Esta es una respuesta indirecta, no responde la pregunta de estilo directamente, pero es la respuesta práctica en general, por lo que vale la pena mencionarla.
Me resulta extremadamente raro tener que escribir condicionales de varias líneas. Hay dos factores para esto:
- No ajuste el código en 80 columnas. El consejo de PEP-8 sobre este tema es antiguo y dañino; ya pasamos los días de los terminales 80x25 y los editores que no pueden manejar de forma sensata el embalaje. 100 columnas están bien, y 120 también es aceptable, también.
- Si las condiciones se vuelven tan largas que todavía necesitan envolverse, generalmente es razonable sacar parte de la lógica del condicional y convertirla en una expresión separada. Esto también tiende a ayudar a la legibilidad.
A través de mis proyectos recientes, alrededor de 12kloc, solo hay un condicional lo suficientemente largo como para que sea necesario envolverlo; el problema simplemente surge muy raramente. Si necesita hacer esto, entonces, como dice nosklo, hállelo por separado; como ha notado, hilvaándolo al mismo nivel que el bloque debajo de él es confuso y difícil de leer.
Esto es lo que hago:
if (collResv.repeatability is None or
collResv.somethingElse):
collResv.rejected = True
collResv.rejectCompletely()
Lo haría de esta manera. Guárdelo con sangría para no confundirse.
if (collResv.repeatability is None or
collResv.somethingElse):
collResv.rejected = True
collResv.rejectCompletely()
El asesoramiento de PEP-8 está aquí.
http://www.python.org/dev/peps/pep-0008/#indentation
A continuación se recomienda el código
# Aligned with opening delimiter
foo = long_function_name(var_one, var_two,
var_three, var_four)
# More indentation included to distinguish this from the rest.
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
Abajo no se aconseja el código
# Arguments on first line forbidden when not using vertical alignment
foo = long_function_name(var_one, var_two,
var_three, var_four)
# Further indentation required as indentation is not distinguishable
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
PEP-8 en realidad parece contradictorio aquí. Mientras que el ejemplo en "Longitud máxima de línea" muestra el uso de paréntesis y una sangría estándar de 4 caracteres, la sección "Sangría" dice, con respecto a las declaraciones de función, "sangría adicional debe usarse para distinguirse claramente como una línea de continuación. ". No veo por qué esto se limitaría solo a "def" y no a "si".
Pep-8 recomienda la manera en que sangraste tu ejemplo original.
Ahora, si estás dispuesto a volar frente a las tan sagradas guías de estilo :-) puedes mover al operador a la siguiente línea:
if (collResv.repeatability is None
or collResv.somethingElse):
collResv.rejected = True
collResv.rejectCompletely()
No soy realmente un admirador de esto, realmente encuentro que su sintaxis original es bastante fácil de leer y no pasaría mucho tiempo monkeying con la sangría o los saltos de línea.
Un problema con todas las sugerencias anteriores aquí es que los operadores lógicos para las condiciones posteriores se ponen en la línea anterior. Imo, eso lo hace menos legible.
Recomiendo poner el operador lógico en la misma línea que la condición que agrega a la instrucción if.
Esto en mi opinión, es mejor
if (None == foo
and None == bar
or None == foo_bar):
que esto:
if (None == foo and
None == bar or
None == foo_bar):
Una opción que a veces uso (aunque no estoy completamente convencido de su legibilidad):
if (collResv.repeatability is None or
collResv.somethingElse
):
collResv.rejected = True
collResv.rejectCompletely()
Posiblemente sería más legible de esta manera:
if (
collResv.repeatability is None or
collResv.somethingElse
):
collResv.rejected = True
collResv.rejectCompletely()