LA FUNCIÓN MAIN()

FLORACIÓN DE LA CRESTA DE GALLO EN LOS MONTES DE SANTA ÚRSULA, EN EL CORAZÓN DEL MONTEVERDE, CENTRO-NORTE DE TENERIFE.

     la función main(), realmente, es un nombre para una función def establecida por convención entre los programadores de Python. Su traducción del inglés, 'principal', nos proporciona una pista clara de su razón de ser.
En nuestra vida real, todas las acciones complejas se subdividen en 'subacciones' que se ejecutan o desarrollan en un orden determinado para conseguir un fin deseado. Todos sabemos que las casa empiezan a construirse por el sótano o los basamentos y no por el tejado: primero las bases, luego las estructuras de alzada del primer piso, a continuación la de los pisos superiores y, finalmente, el tejado. Si lo hacemos por este orden, el único posible, todo nos irá bien. Si no lo hacemos así, ¡vas listo, chaval! 😩. 
Así ocurre en la mayoría de los órdenes complejos de la vida: nuestra educación, nuestra promoción en el trabajo, la construcción de casi cualquier cosa que podamos imaginar, la vida misma (nacemos, crecemos, nos desarrollamos y morimos, y no al revés). 
Y, cómo no, lo mismo ocurre con el código de cualquier lenguaje de programación que se nos ocurra y, por supuesto, en Python.
La función main() desempeña un doble papel: cuando elaboramos un programa, un script con varias funciones def en su interior, a veces se hace necesario proporcionar un ORDEN DE JERARQUÍA al intérprete de Python para que éste sepa por qué función debe comenzar a ejecutarse nuestro script. A esta función es a la que llamamos main() de tal modo que, cuando el programa comience a correr, se encuentre con una función con ese nombre, ejecutándola en primer lugar, y, de manera escalar, prosiga ejecutándose el resto de funciones en el orden en que hayamos dispuesto sus llamadas respectivas (recordemos, sus nombresdef nombre_función(...):) en el cuerpo de la función main(), al margen de otras posibles instrucciones que queramos insertar.
Este comportamiento donde se requiere de una función específica que actúe como punto de entrada o acceso, es muy común en los lenguajes compilados, como Python, C (en el que se basa Python), Java, Go, Rust, etc...
Como podemos deducir, la función main() establece un flujo de lectura propio alternativo al que Python desarrolla de manera predeterminada y que ya conocemos (de izquierda a derecha y, lo que nos interesa, de arriba a abajo). De hecho, esta disrupción del flujo afecta a la propia función main(), que podremos colocar en cualquier parte de nuestro script pues sabemos que Python la ejecutará primero en el comienzo mismo del proceso de lectura.



Podemos construir una función main() primero y, a continuación, modelizar el resto de funciones de nuestro código. Cuando hayamos concluido, podemos invocar a la información contenida en main(), llamando a la función, para que establezca el flujo de ejecución que hayamos previsto.

EXTRUSIÓN DE LAVA EN FORMA DE COLUMNA EN EL MALPAÍS DEL CHINYERO, CON EL MANCHÓN DE PINAR AL FONDO, RESTO DE LA ÚLTIMA ERUPCIÓN VOLCÁNICA DE TENERIFE HACIA EL 18 DE NOVIEMBRE DE 1909, OESTE DE TENERIFE.

Esta función especial main() no lleva necesariamente ninguna sentencia return como pie de función, máximo si le proporcionamos en exclusiva esta  funcionalidad (tampoco lleva print()), dado que su trabajo no pasa por devolver resultado alguno fruto de su ejecución interna, sino en dar comienzo a un flujo específico de lectura/ejecución.
Veamos un ejemplo:


En este ejemplo, hemos creado varias funciones que, posteriormente, hemos ejecutado en un orden preciso desde la función main(). Obviamente, tenemos que declarar como global el dato lado (l, en el ejemplo) que proporciona la ejecución de la función lado(), necesariamente, la primera que debe ejecutarse dado que su valor, es imprescindible para la ejecución del resto, y para que este valor sea accesible a todas, incluida a la propia función main() como veremos en un ejemplo posterior, tenemos que sacarla, extraerla, liberarla del ámbito cerrado de la función asignándole la condición de global con la simple y escueta sintaxis que ya conocemos.



Como podemos comprobar en el ejemplo anterior podemos modificar el flujo de lectura/ejecución a nuestro antojo.
Aunque no tiene mucho sentido desde el punto de vista funcional e, incluso, no sea particularmente recomendable, es posible introducir código ejecutable en el cuerpo de la función principal main() de nuestro código. Obviamente, lo ejecutará en el orden en que lo encuentre. En el ejemplo siguiente, como hemos insertado todas las llamadas antes, ejecuta al final el cálculo del perimetro de la figura.



La estructura if  __name__ ==  '__main__' se vincula a un proceso interno de autorreconocimiento, lo que en lenguajes de programación modernos se denomina INTROSPECCIÓN.
En este caso hablamos del atributo especial __name__, fácilmente reconocible por su sintaxis singular similar a la de los métodos especiales que estudiaremos en la Programación Orientada a Objetos (el primer doble guión bajo sirve para mantener en modo 'constante' al nombre del atributo y no nos sea posible modificarlo en tanto que, en última instancia, es una variable y, de paso, evitar conflictos ulteriores de espacios de nombre. Y algo de esto justifica también el uso de __name__ como veremos. El segundo doble guión bajo es más decorativo, por así decirlo, para distinguir su especificidad al primer vistazo.
__name__ define un espacio de nombres (namespace) exclusivo que permite al intérprete de Python identificar de manera unívoca cualquier módulo *.py en el sistema de importación y que apunta, específicamente, al que se está ejecutando de manera análoga a como actúa main(), que permite al intérprete de Python establecer la función de comienzo de ejecución, recordemos, la función principal, pero en este caso, a nivel de módulos .py. de modo que, en lugar de atender a un determinado orden de ejecución de funciones def en un script, como en los ejemplos anteriores, nos situamos en esta ocasión a nivel de módulos (qué módulo se van a ejecutar primero, unos antes que otros,  entre varios módulos importados en nuestro código).


¿Y cuál es su función? ¿Qué es lo que hace? Pues, básicamente, comprueba si un un módulo *.py se está importando a nuestro código y establece, de ser así (y de ahí el condicional if) que sea el módulo actual el principal, el que asume el papel de main(), aquél que deberá ejecutarse primero, mientras que el módulo importado se ejecutará a continuación.



CRESTERÍA DE DIQUES VOLCÁNICOS EROSIONADOS SOBRE EL VALLE DE SANTIAGO, AL FONDO. OESTE DE TENERIFE.

Dicho de otro modo, si hemos construido un archivo, un módulo, vamos, en la terminología del lenguaje, al que denominamos mi_archivo_python.py y lo estamos ejecutando como programa principal, el valor que asume el atributo especial __main__ que apunta al nombre de nuestro archivo mi_archivo_python.py será el de '__main__', mientras que si usamos ahora el mismo archivo mi_archivo_python.py mediante una importación desde otro módulo distinto con la sintaxis import mi_archivo_python el valor del atributo __name__ será ahora igual a mi_archivo_python pero no '__main__'. Así con if  __name__ ==  '__main__' comprobamos si un determinado módulo ha sido importado o no, de modo que si no ha sido así, si no se ha importado, (si la condición de if no se cumple) se ejecute como principal.

LAURISILVA Y NIEBLA EN VALLE BROSQUE, MACIZO DE ANAGA, NORESTE DE TENERIFE.

Centrémonos ahora en el condicional if __name__ == "__main__" que nos encontraremos infinidad de veces al pie de un script o de un módulo *.py con que nos tropecemos por ahí.
Y para empezar, pensamos que lo mejor es mostrar un esquema:



Aunque resulta un poco engorroso, nos lo resultará menos si seguimos el orden de los números: 1, 2, 3 y 4. Básicamente, Python evaluará mediante el condicional if __name__ == "__main__" si, en efecto, la variable especial __name__  es igual (operador de comparación ==) a __main__ siempre y cuando se lea desde una entrada estándar, una secuencia de comandos o un indicador interactivo, que apunta, más bien, a un ámbito (scope) donde tiene lugar la ejecución del código a nivel superior (y el nivel superior es el ecosistema donde el intérprete de Python, que nos permite a nosotros, programadores, y al lenguaje comunicarnos sin necesidad de tener que conocer, a Dios gracias, ni una coma del código máquina, es el espacio donde se desenvuelve contento y feliz como una lombriz).
Veamos qué sucede si usamos una función main() dentro de un código cualquiera pero no incluimos el condicional if __name__ == "__main__":



Veamos ahora qué sucede si la incluimos:


¿Cómo cambia el cuento, eh?
Como __main__ sólo apunta, en realidad, a un ámbito de ejecución, lo dicho, de nivel superior, no necesariamente tenemos que bautizar a una función que queramos principal como main() para que se ejecute en primer lugar. Lo vemos:


¡Vaya! Y, ya puestos, por la misma razón ni siquiera es necesario que exista una función con el nombre main():


Como estamos en racha, vamos a probar ejecutando como principal un módulo python cualquiera. Vamos allá:


Y ahora. la traca final (y quizás nos lo perdonéis algún día): a partir de Python 3, ya no es necesario recurrir a la instrucción if __name__ == "__main__". Basta tan sólo con sustituir el condicional por una llamada a la función corriente y moliente: main().


PLANICIE DE PUMITA SOBRE SUSTRATO LÁVICO EN EL CORAZÓN DE LAS CAÑADAS DEL TEIDE, A UNOS DOS MIL METROS DE ALTURA. EN INVIERNO SE CUBRE DE NIEVE Y EN PRIMAVERA, CUANDO SUBEN LAS TEMPERATURAS, LA NIEVE SE FUNDE Y GENERA UNA  DE LAS LAGUNAS ESTACIONALES MÁS ALTAS DE ESPAÑA. PARQUE NACIONAL DE LAS CAÑADAS DEL TEIDE, TENERIFE.



37 comentarios:

  1. Una pieza magistral de sabiduria para los que estamos aprendiendo python. Muchas gracias!

    ResponderEliminar
    Respuestas
    1. Muchísimas gracias a ti, Aldo. por tu comentario. Una gran alegría el poder servirte de ayuda. Saludos y mucho ánimo con Python.

      Eliminar
  2. Muchas gracias, de las mejores explicaciones que vi.

    ResponderEliminar
    Respuestas
    1. Gracias a ti, Jose. Muy feliz de poder ayudarte a ti y a cuantos se quieran acercar a este lenguaje de programación. Ojalá pueda seguir haciéndolo. Saludos.

      Eliminar
  3. Respuestas
    1. Muchísimas gracias, Jose. Discúlpame que te responda tan tarde pero no me había avisado de este comentario suyo hasta ahora que lo acabo de ver revisándolos. Saludos.

      Eliminar
  4. muy bueno, me quedo mucho mas claro, estoy aprendiendo y esto ayuda, saludos

    ResponderEliminar
    Respuestas
    1. Gracias, ErrorCode106. Muy amable de tu parte. Mucho ánimo y suerte con tus estudios. Saludos.

      Eliminar
  5. Buenos días, creatu123blog.blogspot.com. No entiendo bien tu pregunta. Si a lo que te refieres es a si dispone de algún método, no lo tiene. El método es en sí la propia función. Recuerda que en última instancia es una simple función definida por nosotros mismos a la que ponemos esa etiqueta de main, que además lleva ese nombre por convención, para que Python la ejecute nada más arrancar el programa, sin otra finalidad.

    ResponderEliminar
  6. Gracias por tomarte el tiempo de compartir tu conocimiento

    ResponderEliminar
    Respuestas
    1. Muchas gracias, Arturo. Lo mejor de este mundo es compartir y, si con ello nos echamos una mano entre todos, además es un placer. Saludos.

      Eliminar
  7. Brother, excelente me gusto mucho. Estoy un poco atascado, en una parte de un codigo que estoy escribiendo, como puedo comparar el resultado de dos funciones ? por ejemplo, estoy utilizando el API de un broker, dentro de las funciones le solicito que me promedie el valor de cierre de los ultimos 21 dias de x valor y otras funcion queme promedia el cierre de los ultimos 13 dias de x valor, como hago para comparar esas funciones?
    es decir, comparar el resultado de los numeros que me dan. Porque intento llamarlos inclusive desde global, pero no me da, te agradezco.

    ResponderEliminar
    Respuestas
    1. Muchas gracias, Csr_Varela. Un placer ayudar, como siempre. Por lo que entiendo, lo que buscas es un Closure o, en el caso de una codificación más avanzada, una Clase. Te ofreceré una respuesta en el apartado Closures (https://conocepython.blogspot.com/search?q=closures) que encontrarás en esta url del sitio, pues es ahí donde debe estar correspondiente al VIERNES, 23 DE NOVIEMBRE DE 2018, si prefieres buscarlo por fechas en el ménú de entradas del lateral derecho. Saludos.

      Eliminar
  8. Hola! muchisimas gracias!

    ResponderEliminar
    Respuestas
    1. Hola, Joel. Gracias a ti por tus palabras y por elegirnos. Saludos.

      Eliminar
  9. Muchísimas gracias, Lisette. A ti. Saludos.

    ResponderEliminar
  10. Buen blog, explicaciones concisas y claras, bonitas fotos. Saludos desde el Sur de isla

    ResponderEliminar
  11. Muchísimas gracias. Siempre es un placer recibir comentarios como el suyo. Y en esta ocasión, por partida doble, al saberlo/a compatriota de nuestra patria chica. Saludos.

    ResponderEliminar
  12. Respuestas
    1. Muchísimas gracias por su comentario. Un placer. Saludos.

      Eliminar
  13. Muchas gracias Excelente me encanto y quite muchas dudas que yo tenia

    ResponderEliminar
    Respuestas
    1. Hola, vcitorh6811@hotmail.com. Gracias a usted por su comentario. Una alegría enorme haberle despejado sus dudas. Esperamos que nuestro blog le siga sirviendo de apoyo y estímulo en su aprendizaje. Saludos.

      Eliminar
  14. Gracias por aliviar mi vista con tan preciosas fotos,buen trabajo un Saludo

    ResponderEliminar
  15. Muchas gracias. Un placer. Saludos.

    ResponderEliminar
  16. Muy interesante, el articulo en especial para las personas novatas que somos en Python.
    mi duda es por ejemplo si me piden hacer tres tipos de funciones, esas funciones se pueden invocar en otro archivo con el código que invoque dicha función.

    ResponderEliminar
  17. Hola, Melek Eyzaguirre. Muchas gracias por tus palabras. Espero que este artículo como los del resto del blog sean de interés y utilidad para todos. En cuanto a su pregunta, la respuesta es sí. Tan sólo tiene que crear una, dos, tres o un millón de funciones distintas en un módulo cualquiera (ya sabe: nombre_archivo.py, por ejemplo, a.py); a continuación crea otro módulo distinto (nuevo_nombre_archivo.py, por ejemplo, b.py), normalmente, en el mismo directorio donde ha creado el primero (por ejemplo, en el Escritorio) y, mediante la cláusula import más el nombre que Ud, le ha proporcionado al módulo, en este caso, import a (sin la extensión, cuidado) en b.py, por la sintaxis del punto, puede llamar a cualquier función que Ud. haya construido en a.py desde b.py:

    import a
    a.funcion1()
    a.funcion2()
    a.funcion3()
    etc.

    ResponderEliminar
  18. Profesor. Muchas gracias por esta explicación,muy valiosa. La verdad llevaba mucho tiempo sin comprender el tema de Main(). Cada vez que ingreso a esta página me dan ganas de quedarme. Voy a aprender todos los temas desde aquí. Éxitos!

    ResponderEliminar
  19. Hola de nuevo, Bayron. Muchas gracias por el comentario. Feliz aprendizaje. Saludos.

    ResponderEliminar
  20. jajaja gracias por explicarlo todo Gauber, es gracioso que leí todo al detalle para comprenderlo. y al final me encuentro con el críptico: main() jajaj buen blog.
    y... Ey, las fotos de la naturaleza con su descripción son muy interesantes, refrescan tu mente para seguir la lectura. Buen detalle.

    ResponderEliminar
  21. Muchísimas gracias por tu comentario. Sí, es cierto, main() tiene esas cosas... En efecto, así es: las fotos están para eso. Saludos.

    ResponderEliminar
  22. Tremenda explicación. Por fin logré comprenderlo. Muchísimas gracias ❤️

    ResponderEliminar
  23. Excelente muchas gracias! . Nota: Algunos de los enlaces hacia los libros no estaban disponibles.

    ResponderEliminar
    Respuestas
    1. Hola. Muchísimas gracias por su comentario. Imagino que se refiere a los enlaces que recogemos en 'HERRAMIENTAS Y UTILIDADES', en el margen superior derecho. Es normal que con el paso del tiempo algunas webs y enlaces estén caídos. En este caso, lo mejor es guardar el título de su interés en el portapapeles y hacer una búsqueda a través de su navegador favorito. Saludos.

      Eliminar