¿Cuál es la forma pythonica de inicialización de variables condicionales?

Debido a las reglas de scope de Python, todas las variables una vez inicializadas dentro de un scope estarán disponibles a partir de entonces. Dado que los condicionales no introducen un nuevo scope, las construcciones en otros idiomas (como inicializar una variable antes de esa condición) no son necesariamente necesarias. Por ejemplo, podríamos tener:

def foo(optionalvar = None): # some processing, resulting in... message = get_message() if optionalvar is not None: # some other processing, resulting in... message = get_other_message() # ... rest of function that uses message 

O, podríamos tener en su lugar:

 def foo(optionalvar = None): if optionalvar is None: # processing, resulting in... message = get_message() else: # other processing, resulting in... message = get_other_message() # ... rest of function that uses message 

Por supuesto, las funciones get_message y get_other_message pueden ser muchas líneas de código y son básicamente irrelevantes (se puede suponer que el estado del progtwig después de cada ruta es el mismo); El objective aquí es preparar el message para su uso más allá de esta sección de la función.

He visto el último constructo usado varias veces en otras preguntas, tales como:

  • https://stackoverflow.com/a/6402327/18097
  • https://stackoverflow.com/a/7382688/18097

¿Qué construcción sería más aceptable?

Python también tiene un patrón de syntax muy útil si puedes usar aquí

  message = get_other_message() if optional_var else get_message() 

O si quieres comparar estrictamente con ninguno

  message = get_other_message() if optional_var is not None else get_message() 

A diferencia del ejemplo 1), este mensaje no se llama a get_message () innecesariamente.

En general, el segundo enfoque es mejor y más genérico porque no implica llamar a get_message incondicional. Lo que puede estar bien si esa función no es un incentivo de recursos pero considera una función de búsqueda

 def search(engine): results = get_from_google() if engine == 'bing': results = get_from_bing() 

Obviamente, esto no es bueno, no puedo pensar en un escenario tan malo para el segundo caso, por lo que básicamente es un enfoque que analiza todas las opciones y finalmente el valor predeterminado es el mejor, por ejemplo.

 def search(engine): if engine == 'bing': results = get_from_bing() else: results = get_from_google() 

Creo que es más python no establecer una regla explícita sobre esto, y en vez de eso, se debe tener en cuenta que las funciones más pequeñas son mejores (en parte porque es posible tenerlas en cuenta cuando se introducen nuevos nombres).

Sin embargo, supongo que si sus pruebas condicionales se vuelven mucho más complicadas que un ” if/else , puede correr el riesgo de que todas ellas fallen y luego usar un nombre no definido, lo que resultará en un posible error de tiempo de ejecución, a menos que tenga mucho cuidado. Eso podría ser un argumento para el primer estilo, cuando sea posible.

La respuesta depende de si hay efectos secundarios de get_message() que se desean.

En la mayoría de los casos, claramente el segundo gana, porque el código que produce el resultado no deseado no se ejecuta. Pero si necesita los efectos secundarios, debe elegir la primera versión.

Podría ser mejor (lea: más seguro) inicializar su variable fuera de las condiciones. Si tiene que definir otras condiciones o incluso eliminar algunas, el usuario del message más adelante podría obtener una excepción de variable sin inicializar.