2010-08-16 9 views
5

Estoy seguro de que este concepto ha surgido antes pero no puedo encontrar una respuesta buena y simple. ¿Está utilizando try/finally una mala forma de manejar funciones con retornos múltiples? Por ejemplo, tengopython try/finally para control de flujo

 

try: 
    if x: 
     return update(1) 
    else: 
     return update(2) 
finally: 
    notifyUpdated() 
 

Esto sólo parece mejor que el almacenamiento de actualización() comandos en una variable temporal y regresar eso.

Respuesta

11

yo no lo recomendaría. Primero porque se llamará notifyUpdated() incluso si el código en cualquiera de las ramas arroja una excepción. Lo que se necesita algo como esto para conseguir realmente el comportamiento previsto:

try: 
    if x: 
     return update(1) 
    else: 
     return update(2) 
except: 
    raise 
else: 
    notifyUpdated() 

En segundo lugar, porque try bloques generalmente indican que estás haciendo algún tipo de control de excepciones y no está, sólo estás utilizarlos para conveniencia. Entonces esta construcción confundirá a las personas.

Por ejemplo, no creo que ninguna de las dos primeras personas (al menos una de las cuales eliminó su respuesta) para responder a su pregunta se dio cuenta de lo que realmente estaba tratando de hacer. El código confuso es malo, no importa cuán conveniente e inteligente parezca.

+0

Un buen punto es tan confuso que las dos primeras respuestas pasaron por alto la marca. –

0

de http://docs.python.org/library/contextlib.html:


from contextlib import closing 
import urllib 

with closing(urllib.urlopen('http://www.python.org')) as page: 
    for line in page: 
     print line 

para que pueda crear una función similar y usarlo

+0

realidad no abordar la cuestión PO. – Omnifarious

+0

'with' stmt es una forma legítima de garantizar la limpieza al cerrar – amwinter

3

Creo que significa que desea usar try/finally como alternativa a esto:

if x: 
    result = update(1) 
else: 
    result = update(2) 
notifyUpdated() 
return result 

supongo que esto es una cuestión de estilo. Para mí, me gusta reservar try para el manejo excepcional condicional. No lo usaré como una declaración de control de flujo.

+0

Aunque supongo que es una cuestión de estilo, no creo que eso signifique que la pregunta no tenga una respuesta de sí o no. Diría definitivamente 'no' por la razón que usted indicó y porque es más confuso. – Omnifarious

+0

Estoy de acuerdo. Debería tomar una postura más fuerte. –

11

No utilizaría try/finally para flujo que no implique excepciones. Es demasiado complicado por su propio bien.

Esto es mejor:

if x: 
    ret = update(1) 
else: 
    ret = update(2) 
notifyUpdated() 
return ret 
3

creo que esto es buscar problemas. ¿Qué pasa después, cuando cambias tu código a lo siguiente?

try: 
    if x: 
     return update(1) 
    elif y: 
     return update(2) 
    else: 
     return noUpdateHere() 
finally: 
    notifyUpdated() # even if noUpdateHere()! 

A lo sumo, es un punto de tropiezo para la mayoría de los lectores del código (probablemente incluso en seis meses), porque está utilizando try/finally para un propósito que se diferencia de los patrones normales de uso. Y el tipeo que guarda es mínimo, de todos modos.

+0

Me perdí ese punto de tropiezo. Ese caso ya existe en forma oculta en el original, porque si 'update (1)' o 'update (2)' lanzan una excepción que también probablemente signifique que 'notificarUpdated()' no debería invocarse. – Omnifarious

3

creo que un decorador es una mejor idea aquí

def notifyupdateddecorator(f): 
    def inner(*args, **kw): 
     retval = f(*args, **kw) 
     notifyUpdated() 
     return retval 
    return inner 

@notifyupdateddecorator 
def f(x): 
    if x: 
     return update(1) 
    else: 
     return update(2) 

@notifyupdateddecorator 
def g(x): 
    return update(1 if x else 2) 
+0

Hmm, nunca he visto esto sobre decoradores personalizados. ¿Tiene un enlace a donde se describe esto? – Falmarri

+0

@Falmarri, http://docs.python.org/glossary.html#term-decorator –

Cuestiones relacionadas