2010-03-26 31 views
41

¿Hay alguna manera en python de convertir un try/except en una sola línea?Python: instrucción try en una sola línea

algo así como ...

b = 'some variable' 
a = c | b #try statement goes here 

Dónde b es una variable declarada y no es c ... así c lanzaría un error y se convertiría en ab ...

Respuesta

34

No hay forma de comprimir un bloque try/except en una sola línea en Python.

Además, es una pena no saber si existe una variable en Python, como lo haría en algunos otros lenguajes dinámicos. La manera más segura (y el estilo prevaleciente) es establecer todas las variables en algo. Si no puede ser que consiga establecer, poned para None primera (o 0 o '' o algo si es más aplicable.)


Si hace asignar todos los nombres que le interesan en primer lugar, que haces tener opciones

  • La mejor opción es una declaración if.

    c = None 
    b = [1, 2] 
    
    if c is None: 
        a = b 
    else: 
        a = c 
    
  • La opción de una línea es una expresión condicional.

    c = None 
    b = [1, 2] 
    a = c if c is not None else b 
    
  • Algunas personas abusan del comportamiento de los cortocircuitos de or para hacer esto. Esto es propenso a errores, así que nunca lo uso.

    c = None 
    b = [1, 2] 
    a = c or b 
    

    Considere el siguiente caso:

    c = [] 
    b = [1, 2] 
    a = c or b 
    

    En este caso, probablemente a debe ser [], pero es porque [1, 2][] es falso en un contexto booleano. Como hay muchos valores que pueden ser falsos, no utilizo el truco or. (Este es el mismo problema las personas se producen cuando dicen if foo: cuando quieren decir if foo is not None:.)

+0

Gracias. El problema es que realmente es una consulta de django model.objects.get que estoy tratando de probar. el .get devuelve un error si no se encuentran datos ... no devuelve Ninguno (lo que me molesta) – Brant

+2

@Brant, entonces ¿por qué no puedes ver el error? ¿por qué una línea? –

+0

@Brant, bien, esa situación es un poco diferente a comprobar si se establece una variable (no se declaran variables en Python). El estilo típico en Python es preferir elevar las excepciones a los errores de retorno como valores, lo que a muchos de nosotros nos encanta. Tener que verificar el código de retorno de una operación cada vez y tener dificultades para rastrear los errores si no lo hago es algo que definitivamente no echo de menos cuando escribo Python. En cualquier caso, aunque ha sido discutido, no hay una sintaxis de una sola línea para un bloque 'try' /' except'. Afortunadamente, las líneas son baratas, por lo que la solución de 4 líneas debería funcionar para usted. ;-) –

2

Usted ha mencionado que está usando Django. Si tiene sentido para lo que está haciendo es posible que desee utilizar:

my_instance, created = MyModel.objects.get_or_create() 

created habrá Verdadero o Falso. Quizás esto te ayude.

4

Puede hacerlo accediendo al espacio de nombres dict usando vars(), locals(), o globals(), el que sea más apropiado para su situación.

>>> b = 'some variable' 
>>> a = vars().get('c', b) 
+3

Esto no funciona exactamente igual que verificando si se establece una variable (aunque sí si está interesado en un alcance particular). Además, ewwwwwwww ..... –

53

Esto es terriblemente hacker, pero lo he usado en el indicador cuando quería escribir una secuencia de acciones para la depuración:

exec "try: some_problematic_thing()\nexcept: problem=sys.exc_info()" 
print "The problem is %s" % problem[1] 

En su mayor parte, no estoy molesto por la restricción no-single-line-try-except, pero cuando estoy experimentando y quiero que readline recuerde todo un fragmento de código a la vez en el intérprete interactivo para poder ajustarlo de alguna manera, este pequeño el truco es útil.

Para el propósito real que intentas lograr, puedes probar locals().get('c', b); idealmente, sería mejor usar un diccionario real en lugar del contexto local, o simplemente asignar c a Ninguno antes de ejecutar cualquier cosa que pueda o no pueda establecerlo.

+12

¡Oye, esto responde la pregunta! :) –

+2

Me encanta esta respuesta, súper desordenado, pero una línea, de la manera que me gusta. –

+0

¡Esta es la respuesta! ¿'problema [0] 'devuelve lo que devuelve esa función? – SIslam

3

Otra forma es definir un gestor de contexto:

class trialContextManager: 
    def __enter__(self): pass 
    def __exit__(self, *args): return True 
trial = trialContextManager() 

A continuación, utilice la declaración with para ignorar los errores en una sola línea:

>>> with trial: a = 5  # will be executed normally 
>>> with trial: a = 1/0 # will be not executed and no exception is raised 
>>> print a 
5 

Sin excepción serán levantados en el caso de un tiempo de ejecución error. Es como un try: sin el except:.

+1

Esto es genial! Como no hay una prueba/excepción explícita, ¿podría explicar brevemente cómo el administrador de contexto se ocupa de los errores? – Patrick

0

El problema es que realmente es una consulta de django model.objects.get que estoy tratando de probar. la .get devuelve un error si no se encuentran datos ... no vuelve Ninguno (que me molesta)

usar algo como esto:

print("result:", try_or(lambda: model.objects.get(), '<n/a>')) 

Dónde try_or es una función de utilidad definida por que:

def try_or(fn, default): 
    try: 
     return fn() 
    except: 
     return default 

Opcionalmente se puede restringir los tipos de excepciones aceptadas a NameError, AttributeError, etc.

1
parse_float = lambda x, y=exec("def f(s):\n try:\n return float(s)\n except: return None"): f(x) 

Siempre hay una solución.

Cuestiones relacionadas