2009-05-02 19 views
10

Cuál es la forma Pythonic para designar código inalcanzable en Python como en:cómo designar código Python inalcanzable

gender = readFromDB(...) # either 'm' or 'f' 
if gender == 'm': 
    greeting = 'Mr.' 
elif gender == 'f': 
    greeting = 'Ms.' 
else: 
    # What should this line say? 
+5

tal vez debería decir "Pat"? –

+0

No creo código inalcanzable es el término correcto para esto. Ver http://en.wikipedia.org/wiki/Unreachable_code – Unknown

+0

@unknown ¿Qué sugeriría usted en su lugar? Sé que este ejemplo no es tan bueno, ya que el ciclo else es de facto alcanzable. Pero sucede que esa es exactamente la "medida de accesibilidad" que estoy buscando. – phihag

Respuesta

24
raise ValueError('invalid gender %r' % gender) 
+1

Desde el manifiesto Pythonic ... "... Los errores nunca deben pasar en silencio. A menos que explícitamente silenciados." – jottos

7

Esto depende de cómo asegurarse de que está siendo del sexo, ya sea 'm' o 'f'.

Si está absolutamente seguro, use if...else en lugar de if...elif...else. Simplemente lo hace más fácil para todos.

Sin embargo, si existe la posibilidad de datos mal formados, probablemente deba hacer una excepción para facilitar las pruebas y la corrección de errores. Usted podría usar un saludo de género neutral en este caso, pero para algo más grande, los valores especiales solo hacen que los errores sean más difíciles de encontrar.

+0

/¿Qué tipo de excepción sugeriría? Y todos parecen quedar atrapados en el ejemplo;). – phihag

+1

Probablemente 'ValueError' según lo sugerido por otros. Parece tener más sentido: http://docs.python.org/library/exceptions.html – zenazn

+1

Hay * siempre * la posibilidad de datos malformados. –

7

Se podría lanzar una excepción:

raise ValueError("Unexpected gender; expected 'm' or 'f', got %s" % gender) 

o utilizar una aserción falsa si espera que la base de datos para devolver sólo 'm' o 'f':

assert False, "Unexpected gender; expected 'm' or 'f', got %s" % gender 
+1

Creo que te refieres a 'assert False' :) – Stephan202

+0

meh, corregido gracias :) – marcog

4

de hecho creo que hay un lugar para esto.

class SeriousDesignError(Exception): 
    pass 

Así que usted puede hacer esto

if number % 2 == 0: 
    result = "Even" 
elif number % 2 == 1: 
    result = "Odd" 
else: 
    raise SeriousDesignError() 

Creo que este es el mensaje de error más significativo. Este tipo de cosas sólo puede surgir a través de los errores de diseño (o mal mantenimiento, que es la misma cosa.)

+1

Todavía incluiría una cadena descriptiva al subir SDE, como 'raise SeriousDesignError ('Los números deben ser par o impar')' – gomad

2

veces hago:

if gender == 'm': 
    greeting = 'Mr.' 
else: 
    assert gender == 'f' 
    greeting = 'Ms.' 

creo que esto hace un buen trabajo de decirle a un lector de la código que solo hay (en este caso) dos posibilidades, y lo que son. Aunque podría hacer un caso para generar un error más descriptivo que AssertionError.

4

Depende exactamente lo que quiere el error de la señal, pero me gustaría usar un diccionario en este caso:

greetings={'m':'Mr.', 'f':'Ms.'} 
gender = readFromDB(...) # either 'm' or 'f' 
greeting=greetings[gender] 

Si el género no es ni m ni f, esto elevará un KeyError que contiene el valor inesperado:

greetings={'m':'Mr.', 'f':'Ms.'} 

>>> greetings['W'] 

Traceback (most recent call last): 
    File "<pyshell#4>", line 1, in <module> 
    greetings['W'] 
KeyError: 'W' 

Si quieres más detalle en el mensaje, se puede tomar & resubida que:

try: 
    greeting = greetings[gender] 
except KeyError,e: 
    raise ValueError('Unrecognized gender %s'%gender) 
3

Hasta ahora, he utilizado generalmente una variación en la respuesta de Juan Fouhy - pero esto no es exactamente correcta, como señala Ethan:

assert gender in ('m', 'f') 
if gender == 'm': 
    greeting = 'Mr.' 
else: 
    greeting = 'Ms.' 

El principal problema con el uso de una aserción es que si alguien va a su código con las banderas -O o -OO, las afirmaciones se optimizan. Como señala Ethan a continuación, eso significa que ahora no tiene ningún control de datos. Las aseveraciones son una ayuda al desarrollo y no deben usarse para la lógica de producción.Voy a entrar en el hábito de usar un cheque() función en lugar - esto permite la sintaxis de llamada limpia como una aserción:

def check(condition, msg=None): 
    if not condition: 
     raise ValueError(msg or '') 

check(gender in ('m', 'f')) 
if gender == 'm': 
    greeting = 'Mr.' 
else: 
    greeting = 'Ms.' 

Volviendo a la pregunta original, yo pretendo que el uso de una valer() o cheque() antes de la si/lógica demás es más fácil de leer, más seguro y más explícito:

  • pone a prueba la calidad de los datos antes de empezar a actuar sobre ella - esto podría ser importante si hay operadores distintos de '==' en la cadena si/else
  • se separa la prueba de la afirmación de la lógica de ramificación, en lugar de entrelazado de ellos - ésimo se hace que la lectura y la refactorización más fácil
+0

Si quieres para verificar previamente debes hacerlo con 'si el género no está en ('m', 'f'): raise SomeException' ya que' assert's se puede optimizar y luego no tienes ninguna verificación. –

+0

Arg. Está bien. Nunca uso -O o -OO así que no me preocupo por mi propio código, pero acepto que es un mal hábito. Repararé la respuesta. – stevegt

Cuestiones relacionadas