31 de diciembre de 2017

4° Congreso Internacional de Innovación Educativa

Del 11 al 13 de diciembre de 2017 se llevó a cabo en la ciudad de Monterrey, Nuevo León, México, el 4° Congreso Internacional de Innovación Educativa (CIIE). Este congreso tiene como objetivo principal que los participantes conozcan las tendencias y prácticas que están revolucionando la educación en el mundo. Esta edición del congreso logró juntar a más de tres mil profesores de 17 países.

Fuente: observatorio.itesm.mx

En el marco de este congreso tuve la oportunidad de fungir como coordinador de un panel titulado “Enseñando a programar usando el lenguaje Python”. Este es su resumen:
El lenguaje de programación Python se ha popularizado en el ámbito educativo en años recientes. Guo (2014) reportó que 8 de las 10 universidades más importantes en el área de ciencia de la computación en los Estados Unidos están actualmente utilizando Python en sus cursos de introducción a la programación. Algunos profesores del Tecnológico de Monterrey también están usando este lenguaje para enseñar a programar a sus estudiantes de diversas carreras profesionales, desde aquellas en el área de TI e ingeniería hasta las de arte y medios digitales. Este panel tiene como intención permitir a varios de estos profesores compartir sus experiencias y reflexiones en el uso de Python en los cursos de Fundamentos de programación (Tc1014) y Solución de problemas con programación (Tc1017). Python provee muchas ventajas como primer lenguaje de programación: tiene una sintaxis y semántica sencilla y consistente, viene con “baterías incluidas” (extensa biblioteca estándar), su naturaleza interactiva lo hace ideal para llevar a cabo experimentación y desarrollo rápido, es software libre y corre en múltiples plataformas (Windows, macOS y Linux). Sin embargo, Python no es un lenguaje perfecto, por lo que también abordaremos en este panel algunas de sus fallas y limitaciones.
El panel estuvo conformado, además de mí, por los siguientes cuatro destacados profesores del Tecnológico de Monterrey:
  • Alma Patricia Chávez Cervantes (Campus Estado de México)
  • Irma María García Barranco (Campus Estado de México)
  • Kenneth William Bauer (Campus Guadalajara)
  • Eduardo Daniel Juárez Pineda (Campus Querétaro)

Los integrantes del panel “Enseñando a programar usando el
lenguaje Python”. Atrás: Patricia Chávez y Ken Bauer. En frente:
Irma García, Ariel Ortiz y Eduardo Juárez.

En el panel se discutieron las ventajas y desventajas que tiene Python como primer lenguaje para enseñar a programar y cómo se compara con otros lenguajes (por ejemplo C, C++ o Java). Así mismo, se presentaron ejemplos de cómo se puede utilizar Python y bibliotecas de terceros para resolver problemas de dominios variados, como son: cómputo científico e ingenieril, procesamiento de medios y programación de microcontroladores. Finalmente, se compartieron experiencias, sugerencias, prácticas y recursos que seguramente resultarán útiles a otros maestros interesados en adoptar Python en sus clases.

Fuente: www.ezlearning.co.uk

El panel fue recibido de manera bastante favorable por el público asistente, compuesto por más de una veintena de personas. En particular, varios profesores de nivel preparatoria se mostraron muy interesados en los temas tratados.


Se pueden consultar las siguientes ligas para encontrar más información sobre este panel y el CIIE 2017 en general:

31 de julio de 2017

pyboard: Python en un microchip

A finales del año 2013, el físico y programador australiano Damien George arrancó desde el Reino Unido una campaña en Kickstarter para recaudar fondos con el fin de desarrollar una plataforma de hardware libre basada en una placa con un microcontrolador que soportara directamente el lenguaje Python. Esencialmente quería diseñar algo parecido a un Arduino, pero que pudiera programarse de manera eficiente en Python en lugar de los lenguajes comúnmente disponibles para programar microcontroladores (C/C++ y ensamblador). La meta inicial de George era recaudar 15,000 GBP (aproximadamente equivalente a 25,000 USD de aquel entonces) para elaborar su proyecto, pero al finalizar la campaña había recaudado 97,803 GBP (más de 160,000 USD). Y así fue como surgió el pyboard.

Damien P. George, creador del pyboard.
Fuente: dpgeorge.net

El software

Central en el proyecto del pyboard fue el desarrollo de MicroPython, un subconjunto de Python 3 elaborado también por Damien George. Al re-escribir este intérprete desde cero, George logró que fuera suficientemente pequeño para poder caber y correr en un microcontrolador.


MicroPython utiliza muy poca memoria RAM e incluye una pequeña fracción de la biblioteca estándar de Python. Aún así, MicroPython soporta características avanzadas como son: enteros de tamaño arbitrario, cerraduras léxicas (closures), listas por comprensión, generadores, manejo de excepciones e incluseo un shell interactivo. Al correr directamente sobre los fierros, MicroPython funge efectivamente como el sistema operativo del pyboard.

Teóricamente, los requisitos mínimos de memoria para que un sistema pueda soportar MicroPython son: 128 kibibytes de ROM y 8 kibibytes de RAM. Gracias a eso ha sido migrado exitosamente a otras plataformas. Además del pyboard, el sitio oficial ofrece el firmware requerido para correr MicroPython en los microchips WiPy, ESP8266, ESP32, Espruino Pico, STM32F4, NUCLEO-L476RG y micro:bit.

El hardware

La placa del pyboard contiene un microcontrolador STM32F405RG de STMicroelectronics con las siguientes características:
  • Procesador RISC de 32 bits ARM Cortex-M4F.
  • Una velocidad de reloj de 168 MHz.
  • Registros de 32 bits: 
    • 16 para valores enteros.
    • 32 para valores de punto flotante de precisión sencilla.
  • 192 kibibytes de memoria RAM para almacenar datos volátiles.
  • 1024 kibibytes de memoria flash ROM para almacenar el código del programa.
  • 13 temporizadores independientes.
  • Soporte de protocolos UART, I2C, SPI y CAN para comunicación con periféricos.
  • Hardware generador de números aleatorios (TRNG, true random number generator).

El pyboard v1.1.
Fuente: MicroPython Store

La placa del pyboard tiene un tamaño de 4.1 cm × 3.2 cm × 0.2 cm y cuenta adicionalmente con los siguientes elementos:
  • Conector micro-USB: sirve como fuente de alimentación y también permite establecer comunicación serial con una computadora anfitriona.
  • Ranura para tarjeta microSD de capacidad estándar (SDSC) y alta capacidad (SDHC).
  • Acelerómetro de tres ejes.
  • Reloj en tiempo real (oscilador de cristal) a 32 kHz.
  • Dos botones: RST (hard reset) y USR (funcionalidad definida por el usuario).
  • Cuatro ledes (colores: rojo, verde, amarillo y azul).
  • 30 pines GPIO (general-purpose input/output).  

Comparando pyboard con Arduino

La principal ventaja de un pyboard sobre un Arduino tiene que ver con la forma en que soportan Python. En diversas entradas de este blog hemos programado el Arduino usando Python, pero no debemos perder de vista que el Arduino debe estar siempre conectado a una computadora anfitriona a través de un cable USB. Esto es así porque el programa de Python corre en el sistema anfitrión y no en el Arduino. El Arduino funge como esclavo que corre un ejecutable (típicamente escrito en C/C++) que implementa el protocolo de Firmata y que le permite establecer una comunicación serial en dos sentidos con el programa que lo controla y que corre en la PC anfitriona. El pyboard, por otro lado, puede correr programas en Python sin necesidad de estar conectado en todo momento a una computadora anfitriona. El pyboard tiene instalado localmente el intérprete de MicroPython y solo basta transferir (vía la conexión USB) a su memoria flash el programa *.py que deseamos correr. Una vez hecho esto, podemos desconectar el pyboard del sistema anfitrión y solo requerimos proveerle a la placa un suministro eléctrico alternativo, por ejemplo un banco de energía (como los que se usan para recargar las pilas de los teléfonos celulares). A partir de ese momento nuestro programa en Python se ejecuta automáticamente al encender o reiniciar el pyboard.

Un pyboard (en su estuche protector)
conectado a un banco de energía.

Cuando el pyboard está conectado a la computadora anfitriona podemos llevar a cabo una sesión interactiva con el shell de MicroPython corriendo directamente sobre la placa. Para lograr lo anterior tenemos que abrir una ventana de línea de comando en el sistema anfitrión y luego correr algún emulador de terminal tonta (por ejemplo screen o picocom) que permita conectarse al pyboard. Cuando corremos el shell podemos jugar y experimentar directamente con todas las facilidades provistas por la placa. El shell también puede ser bastante útil durante el proceso de depuración de nuestros programas. No existe una funcionalidad similar a ésta cuando se programa el Arduino usando C/C++.

El shell de MicroPython corriendo sobre el
pyboard y siendo visualizado en una
ventana de línea de comando en la
computadora anfitriona.

Otra diferencia entre el Arduino y el pyboard son las herramientas de desarrollo que se utilizan. Arduino necesita su propio IDE (ambiente de desarrollo integrado) para editar archivos, compilarlos y transferir los ejecutables a la placa. Para usar el pyboard no necesitamos ningún software especial, salvo el editor de nuestra preferencia. Resulta trivial la transferencia de archivos gracias a que la placa se comporta como una memoria USB al momento de conectarla a la máquina anfitriona, la cual puede estar corriendo Windows, macOS o Linux.

El pyboard tiene otra ventaja sobre Arduino que puede ser benéfica particularmente para principiantes. Al incorporar de fábrica cuatro ledes, un botón y un acelerómetro, es posible elaborar diversos proyectos interesantes en el pyboard sin requerir hardware adicional. Es posible empezar a hacer experimentos sencillos de computación física sin tener la necesidad de conseguir y conectar actuadores, sensores, resistencias y cables a un protoboard.

Caos resultado de un exceso de componentes electrónicos.
Fuente:
Harvard Business Review

Dado que el hardware del pyboard es de mayor capacidad y más sofisticado que la mayoría de los modelos existentes de Arduino, resulta también ser un tanto más costoso. Irónicamente, puede resultar que un programa escrito en C/C++ para Arduino se ejecute más rápido que su equivalente en Python para el pyboard. Esto se debe a que en estas plataformas el código de C/C++ se compila mientras que el de Python se interpreta. Como es bien sabido, los programas interpretados son usualmente más lentos y requieren más memoria que los compilados debido a la necesidad de traducir el código fuente mientras se corre. En la práctica, el impacto en los tiempos de ejecución normalmente no repercute de forma significativa en la mayoría de los programas escritos para el pyboard. Y si esto llegara a ser un problema, existe la opción de escribir porciones limitadas de código en C/C++/ensamblador que pueden ser invocadas desde el código de MicroPython para optimizar los cuellos de botella y obtener así un mejor desempeño pero sin reducir sustancialmente la productividad que se consigue al programar primordialmente en Python.

Comparando pyboard con Raspberry Pi

La Raspberry Pi (RPi) y el pyboard pertenecen a dos categorías diferentes de placas electrónicas. La RPi es una computadora monoplaca (single-board computer) que para fines prácticos es casi una computadora completa. Tiene su propio sistema operativo (usualmente alguna distribución de Linux) y para usarla necesitamos (generalmente) conectarle mouse, teclado y monitor. El modelo 3 de la RPi ya cuenta incluso con Bluetooth y Wi-Fi. Por otro lado, el pyboard (al igual que el Arduino) es un microcontrolador monoplaca (single-board microcontroller). Esto significa que un pyboard es más sencillo y tiene típicamente un propósito más restringido que una RPi. Conviene mencionar que una RPi puede servir de sistema anfitrión para programar a un pyboard.

Por sus características de hardware, una RPi modelo 3 resulta una buena opción para realizar proyectos de IoT (internet de las cosas). En contraste, el pyboard no cuenta con un esquema de comunicación inalámbrica, por lo que no resulta adecuado para este fin.

Al igual que el pyboard y el Arduino (y a diferencia de una PC común y corriente), la RPi cuenta con múltiples pines GPIO (entrada/salida de propósito general) que podemos usar para conectar y controlar diversos componentes, tales como actuadores y sensores. Al momento de programar la RPi podemos usar cualquier lenguaje soportado por su sistema operativo, por ejemplo C, C++, Java, Ruby, Python, Perl, JavaScript, etc. Como ya lo hemos mencionado varias veces, el pyboard está diseñado para programarse en Python.

Fuente: Day Break Tecnologies

Comentarios finales

El pyboard es una opción interesante en el mundo de la computación física. En primera instancia se parece al Arduino pero con el atractivo de que se programa directamente en Python. Lamentablemente es aún poco conocido, y por lo mismo existe menos documentación disponible (comparado con otras plataformas) y resulta complicado adquirirlo en países como México. En Estados Unidos se puede conseguir a través de Amazon.com o Adafruit. La empresa Adafruit realiza envíos de componentes electrónicos a México, pero hay que considerar los impuestos aduanales que se deben pagar al momento en que un producto de este tipo llega al país. En Europa y otras partes del mundo los interesados pueden comprar el pyboard en la tienda oficial de MicroPython. El costo de un pyboard v1.1 varía bastante según el proveedor, pero usualmente comienza en los 35 USD.

31 de mayo de 2017

PyCon 2017

Del 19 al 22 de mayo tuve la oportunidad de asistir a PyCon 2017 en la ciudad de Portland, Oregon, en los Estados Unidos. PyCon es una conferencia anual organizada por la Python Software Foundation con el fin de reunir a la comunidad de desarrolladores, usuarios y entusiastas del lenguaje Python y su correspondiente ecosistema.


Actualmente existen muchas ediciones de PyCon en todo el mundo. Argentina, Colombia, España, Uruguay y Venezuela son algunos de los países hispano parlantes que han tenido una o más conferencias nacionales sobre Python. Sin embargo, PyCon en los Estados Unidos es el encuentro de Python con el mayor número de participantes. Este año tuvo una cifra record de más de 3,300 asistentes.

Centenares de pitonistas esperando que comience una
de las conferencia magistral en PyCon 2017.

En esta entrada del blog de EduPython comentaré sobre mi experiencia e impresiones de PyCon 2017.

La agenda

PyCon 2017 se efectuó en un espacio de nueve días (del 17 al 25 de mayo) con los siguientes cinco eventos centrales:
  • Tutoriales. Sesiones de tres horas para aprender temas nuevos y relevantes.
  • Cumbres. 
    • Cumbre de lenguaje Python: Reunión de los desarrolladores de las diferentes implementaciones de Python (CPython, Cython, Jython, MicroPython, PyPy, etc.) para discutir sobre tecnología y estrategias.
    • Cumbre de educación: Reunión de maestros y educadores enfocados a enseñar programación, usando Python, a públicos amplios y diversos.
  • Conferencias.
    • Pláticas programadas: conferencias magistrales y pláticas en sesiones paralelas.
    • Espacios abiertos (Open Spaces): también conocido como la desconferencia, en la que los propios asistentes toman un papel más participativo y activo en presentaciones y discusiones informales.
    • Charlas relámpago (Lightning Talk): pláticas de cinco minutos de casi cualquier tema.
    • Sala de exposiciones: conformado por stands (puestos) de diversas compañías que usan y respaldan Python o que contratan gente que sabe programar en Python.
    • Sesión de pósteres: académicos, aficionados y miembros de la comunidad muestran su trabajo en forma de póster y responden a preguntas.
  • Feria de empleo. Para personas interesadas en conseguir trabajo en compañías que están utilizando Python y tecnologías relacionadas. Algunas de las empresas que estuvieron presentes fueron: Google, Intel, Microsoft, Linkedin, Red Hat, SurveyMonkey, Heroku, Continuum Analytics, JetBrains, Docker, Yelp, Lyft, Instragram, Facebook, JPMorgan Chase, BuzzFeed, Double Negative y Walt Disney Animation Studios.
  • Esprints de desarrollo. Sesiones de trabajo en las que los interesados pueden trabajar en diversos proyectos de código abierto (Open Source), incluyendo el lenguaje Python.

Arriba: el stand de Walt Disney Animation
Studios en la feria de empleo.

Abajo: mesa de trabajo del proyecto mypy
durante el primer día de esprints.

La comunidad

Lo mejor de PyCon, sin lugar a duda, es su comunidad. Brandon Rhodes, presidente de la mesa directiva de PyCon 2016-17, mencionó en su mensaje inaugural lo orgulloso que él se siente de pertenecer a una comunidad centrada en una herramienta abierta que puede ser usada libremente por todos, desde un estudiante de nuevo ingreso hasta un profesionista, un académico con presupuesto limitado, o incluso una gran empresa. Enfatizó que la comunidad de Python no busca sacarle ventaja al software para hacer que las cosas sean más costosas, sino que, al contrario, busca apoyar y facilitar cualquier tipo de actividad humana y no solo aquellas que cuentan con los medios para desembolsar una cuota.

Brandon Rhodes, presidente de PyCon 2017.

La comunidad de PyCon destaca por su carácter amistoso e incluyente. Un objetivo fundamental de la conferencia consiste en propiciar una experiencia libre de cualquier tipo de acoso, sin importar género, preferencia sexual, discapacidad, apariencia física, tamaño corporal, raza o religión. 

En PyCon no se discrimina a ningún tipo de persona.

El BDFL

Uno de los momentos más memorables que tuve en PyCon fue cuando conocí en persona al mismísimo Guido van Rossum, computólogo neerlandés y autor del lenguaje Python, usualmente conocido (de manera humorística) como el dictador benevolente de por vida (BDFL por sus siglas en inglés). Tuve la oportunidad de platicar con él por un espacio de quince minutos sobre algunos aspectos de su vida personal y laboral. Quedé admirado por su trato sencillo y accesible. Es claro para muchos que su personalidad ha sido un factor clave en la conformación y proceder de la notable comunidad de Python.

Conociendo a Guido van Rossum, el creador de Python.

Un mosaico de ideas e intereses

¿A qué se dedican las personas que asisten a PyCon? Hay una amplia variedad de profesiones representadas: programadores/desarrolladores de software, testers, ingenieros, científicos, investigadores, estudiantes, maestros, directores de tecnología (CTO por sus siglas en inglés) y aficionados que solo programan como hobby. Relacionado a esto, en la conferencia magistral titulada “La efectividad inesperada de Python en la ciencia” el Dr. Jake Venderplas hizo la siguiente observación:
Hay muchos otros congresos relacionados con Python: DjangoCon, la conferencia de SciPy, PyData, AnacondaCON, JupyterCon, etc. Los grupos de personas que asisten a estos congresos son tan solo una delgada “rebanada” de toda la comunidad de Python. Cada uno de estos grupos tiene sus propias herramientas y enfoques para resolver problemas. Pero durante PyCon, todos estamos aquí reunidos. Por esta razón considero que PyCon es de cierta manera como un gran mosaico.

Venderplas posteriormente introdujo a la audiencia a su muy particular “rebanada”: la astronomía. Él se dedica a aplicar estadística, minería de datos y aprendizaje automático para procesar grandes volúmenes de datos generados por telescopios y otros instrumentos de medición astronómica. Resulta que Python es una herramienta central para todo lo que hace de forma habitual en su trabajo.

Jake Venderplas, astrónomo y
científico de datos.

En su plática, Venderplas presentó la siguiente filmina que muestra cómo las menciones de Python se han incrementado en los últimos años en las publicaciones de astronomía, comparado con otras herramientas de software como Fortran, Matlab e IDL (Interactive Data Language):

Menciones de software en publicaciones de astronomía.
El lenguaje Python (línea roja) ha tenido un crecimiento exponencial.

Pero, ¿por qué se ha popularizado tanto el uso Python en la astronomía y en otras áreas de la ciencia? Vanderplas considera que hay cuatro razones para explicar este fenómeno:
  1. Interoperabilidad con otros lenguajes. Python sirve como un “pegamento” para juntar toda la mezcolanza de software científico que hay disponible. Su sintaxis de alto nivel sirve como una envoltura para las bibliotecas escritas en C y Fortran, donde realmente ocurren las operaciones de cómputo intensivo.
  2. Baterías incluidas. La biblioteca estándar de Python permite hacer casi cualquier cosa, y para todo lo demás existe una cantidad inmensa de bibliotecas desarrolladas por terceros. Si tienes algún problema particular, hay una alta probabilidad de que alguien ya haya escrito un paquete en Python para resolverlo.
  3. Simplicidad y dinamismo. Por su naturaleza, el cómputo científico es exploratorio y no lineal. En este contexto, la velocidad para desarrollar un programa suele ser más importante que la velocidad de ejecución.
  4. Apertura. El carácter distintivamente abierto de Python encaja muy bien con la esencia misma de la investigación científica. Actualmente la ciencia pasa por una crisis de replicabilidad. Esto quiere decir que existen muchos estudios publicados los cuales no pueden ser repetidos de manera exitosa. Para que la ciencia pueda progresar se debe seguir un modelo de ciencia abierta (Open Science), el cual toma muchas ideas del movimiento de código abierto (Open Source). Una investigación científica que involucre software debe dar a conocer el código y los datos que produjeron los resultados obtenidos. El código abierto en general, y Python en particular, han servido como ejemplo e inspiración para mejorar las prácticas de la comunidad científica mundial.

Conclusión

El haber participado en PyCon fue una gran experiencia personal. Convivir con una comunidad tan diversa y entusiasta me resultó revigorizante. Me falta tiempo para poder escribir en este espacio sobre todos aquellos temas sumamente interesantes que desconocía o que no me había dado el tiempo de examinar a más detalle. Algunas cosas que descubrí (o redescubrí) en PyCon y que espero poder estudiar más profundamente son: manejo de tipos estáticos con mypy, programación de microcontroladores con MicroPython, escritura y experimentación con notebooks de Jupyter, y uso de pdb para depurar programas de manera interactiva. Ya estaré documentando en este blog lo que vaya aprendiendo.

Pioneer Courthouse Square,
centro de Portland.

Por último, conviene mencionar que los videos de todas las conferencias están disponibles en inglés en el canal de YouTube de PyCon 2017.

22 de abril de 2017

Reconciliando Python 2 y 3

Python 3 fue liberado oficialmente hace más de ocho años. Sin embargo, todavía en el año 2017 existen razones que nos obligan a tener que escribir código para Python 2. Puede ser que necesitemos usar alguna biblioteca o programa preexistente escrito en Python 2. O quizás haya algún servicio en línea para aprender a programar que solo funcione con Python 2, por ejemplo PySchools.com. Tal vez requiramos usar algún servidor remoto de Linux que solamente tenga instalado Python 2, y carecemos de los privilegios de administrador necesarios para instalarle software nuevo. También ocurre que en algunos sitios de programación competitiva sus respectivos jueces en línea solo aceptan soluciones escritas en Python 2, como son los casos de omegaUp y el Caribbean Online Judge (COJ). Sea cual sea la razón, no deja de ser un tanto frustrante tener que estar lidiando con dos versiones del lenguaje.


Como educadores nos surgen varias dudas:
  • ¿Qué versión de Python debemos enseñar a alumnos que están aprendiendo a programar actualmente? 
  • ¿Debemos enseñar Python 2, viendo hacia atrás, privilegiando la compatibilidad con el pasado?
  • ¿Debemos enseñar Python 3, viendo hacia adelante, favoreciendo lo que pueden ser las ideas y prácticas del futuro? 
  • ¿Vale la pena, quizás, enseñar ambas versiones de Python? 
  • ¿Es posible escribir programas que funcionen sin modificaciones en las dos versiones? 
  • Pero para empezar, ¿por qué rayos existen dos versiones rivales de Python?

Un poco de historia

La primera versión pública del lenguaje (Python 0.9.0) apareció en 1991. Las versiones 1.0 y 2.0 fueron liberadas en 1994 y 2000, respectivamente. Para mediados de la década pasada, Guido van Rossum, el autor de Python, consideró que el lenguaje había acumulado, a través de los años, elementos redundantes que iban en contra de la filosofía esencial de Python, la cual establece que: “debe haber una, y de preferencia solamente una, manera obvia de hacer las cosas”. Así pues, Guido decidió que en la siguiente versión mayor de Python (originalmente llamada Python 3000 o Py3K) se eliminaran todos aquellos componentes considerados obsoletos o duplicados con el fin de obtener un lenguaje más limpio y elegante, con una mejor oportunidad de evolucionar positivamente sin tener que cargar con vestigios heredados del pasado. Obviamente, estos cambios provocarían una incompatibilidad con prácticamente todo el código de Python existente en aquel momento. Para facilitar la transición, se decidió que coexistieran durante algún tiempo dos versiones de Python. Así pues, a finales de 2008 teníamos disponibles las versiones 2.6 y 3.0 de Python. Así mismo, se proporcionó la herramienta 2to3 para simplificar la migración de los programas de Python a la nueva versión.

Guido van Rossum

En el año 2010 se liberó Python 2.7, la última versión menor de la rama de Python 2. Originalmente solo iba a ser soportada por cinco años. En otras palabras, se esperaba que para el 2015 todos hubiéramos ya migrado a Python 3. Lamentablemente esto no ocurrió y por eso la fecha de EOL (end of life o fin de vida) de Python 2.7 se extendió hasta el 2020. Esto significa que nos quedan por lo menos tres años en las que las versiones 2 y 3 de Python deberán seguir coexistiendo.

¿Qué hacer?

Yo soy de la opinión de que debemos concentrar nuestros recursos y esfuerzos en enseñar a nuestros alumnos Python 3.x, pues es la versión que tiene un futuro claro. Python 2.7 está actualmente en modo de mantenimiento y en pocos años estará descontinuado. No obstante, cuando veamos que surja la necesidad podemos orientar a nuestros alumnos a que utilicen algunas prácticas relativamente simples que permiten escribir programas que funcionan de manera idéntica tanto en Python 2.7 como en Python 3.x. En lo que resta de esta entrada del blog de EduPython explicaré cómo podemos lograr justamente esto.

Si no sabes qué versión del lenguaje estás utilizando puedes correr el siguiente código desde la consola de Python para averiguarlo:
>>> from sys import version
>>> version
'3.6.0 (default, Jan 13 2017, 00:00:00) \n[GCC 4.8.4]'
En mi experiencia hay cuatro diferencias fundamentales entre Python 2.7 y Python 3.x que pueden generarle algo de ruido a una persona que está aprendiendo a programar:
  • Caracteres especiales
  • Instrucción vs. función print
  • Funciones input y raw_input
  • Operador de división
Hay muchas otras situaciones en donde surgen incompatibilidades, pero con resolver las cuatro anteriores cubrimos las necesidades más comunes de un programador principiante. Para una descripción exhaustiva de cómo escribir código de Python compatible entre las versiones 2 y 3 se puede consultar la siguiente página: Cheat Sheet: Writing Python 2-3 compatible code.

Caracteres especiales

Por omisión, un archivo fuente de Python 2 utiliza el código ASCII como esquema de codificación de caracteres. Bajo este esquema solo podemos usar en nuestros programas las letras del abecedario inglés, los dígitos numéricos y algunos otros símbolos de puntuación. En otras palabras, no podemos usar ciertos símbolos propios del idioma español como son: las vocales con acento agudo u ortográfico (á, é, í, ó, ú, Á, É, Í, Ó, Ú), la letra u con diéresis (ü, Ü), la letra eñe (ñ, Ñ) ni los signos de apertura de interrogación y exclamación (¿, ¡). Si nuestro programa contiene cualquiera de estos caracteres no-ASCII, típicamente dentro de un comentario o en una cadena de caracteres, el intérprete de Python produce un mensaje de error parecido a éste:
SyntaxError: Non-ASCII character '\xc3' in file prueba.py on line 5, but no encoding declared;.
Para evitar este error podemos declarar de manera explícita el esquema de codificación de caracteres que utiliza nuestro archivo fuente de Python. Esto se hace incluyendo un comentario similar al siguiente en la PRIMERA o SEGUNDA línea del archivo (ver el documento PEP 263 para más detalles):
# coding=UTF-8
El formato de transformación de Unicode de 8 bits (UTF-8 por sus siglas en inglés) al que se hace referencia arriba es un esquema de codificación que soporta los caracteres de alfabetos modernos y extintos, sistemas ideográficos y colecciones de símbolos matemáticos, musicales, iconos, etc. Esto significa que podemos usar todos los símbolos del español y muchos más, incluyendo cosas como el signo de euro (€) o los palos de una baraja (♥, ♦, ♣, ♠).

Es importante mencionar que para que todo funcione correctamente el editor que se esté utilizando debe guardar el archivo usando el formato UTF-8 y no algún otro. Esto es algo totalmente transparente para el usuario si se está utilizando un editor diseñado expresamente para Python, como es el caso de IDLE o Spyder. Otros editores pudieran requerir alguna configuración explícita.


Python 3, a diferencia de Python 2, supone por omisión que los archivos fuente utilizan UTF-8 como esquema de codificación de caracteres, por lo que estrictamente es innecesario añadir el comentario “#coding=UTF-8” al inicio del archivo si deseamos usar dicho formato, sin embargo no le hace daño incluirlo y por compatibilidad conviene hacerlo. El documento Unicode HOWTO contiene muchos detalles sobre el uso de Unicode con Python.

Instrucción vs. función print

En Python 2 print es una instrucción mientras que en Python 3 es una función. La implicación más importante es que para invocar una función en Python se necesitan paréntesis pero no es así para una instrucción. Veamos unos ejemplos:
# Usando la instrucción print en Python 2
print 'Existen', 2 ** 10, 'bytes en un kibibyte.'
# Usando la función print en Python 3
print('Existen', 2 ** 10, 'bytes en un kibibyte.')
Al correr ambos códigos en sus respectivas versiones de Python la salida esperada es la misma:
Existen 1024 bytes en un kibibyte.
Sin embargo, si el código de arriba diseñado para Python 3 se corre en Python 2, los paréntesis se interpretan como los delimitadores de una tupla de tres elementos, produciendo una salida que resulta extraña cuando no se sabe lo que está sucediendo:
('Existen', 1024, 'bytes en un kibibyte.')
Por otro lado, si el código de arriba diseñado para Python 2 se intenta correr en Python 3, lo que se obtiene es un error de sintaxis:
  File "ejemplo.py", line 3
    print 'Existen', 2 ** 10, 'bytes en un kibibyte.'
          ^
SyntaxError: Missing parentheses in call to 'print'
Para resolver esta incompatibilidad debemos importar print_function del módulo __future__ al inicio de nuestro programa:
from __future__ import print_function
La instrucción anterior obliga a que print solo pueda usarse como función, independiente de la versión del lenguaje que se esté utilizando, por lo que el siguiente código:
from __future__ import print_function

# Usando print como función en Python 2 y 3
print('Existen', 2 ** 10, 'bytes en un kibibyte.')
produce exactamente la misma salida tanto en Python 2 como en Python 3:
Existen 1024 bytes en un kibibyte.


Al ser función, print tiene el beneficio adicional de que puede recibir varios argumentos de palabra clave:
  • sep: Indica qué cadena se debe utilizar como separador (o delimitador) entre los elementos a imprimir. Por omisión se usa un espacio en blanco (' '). 
  • end: Establece qué cadena se debe utilizar después de haber impreso todos los elementos. Se usa un salto de línea ('\n') en caso de no indicarse.
  • file: Define el archivo en el que se debe realizar la impresión. Si se omite usa la salida estándar (usualmente la pantalla).
El siguiente ejemplo muestra cómo usar todos los argumentos de palabra clave de la función print con la ventaja de que funciona de manera idéntica tanto en Python 2 como en Python 3:
from __future__ import print_function

with open('salida.txt', 'w') as f:
    print(4, 8, 15, sep='-', end='|', file=f)
    print(16, 23, 42, sep='*', end='$', file=f)
El código crea un archivo llamado salida.txt con el siguiente contenido:
4-8-15|16*23*42$

Funciones input y raw_input

Python 2 cuenta con dos funciones que permiten directamente leer datos desde la entrada estándar (usualmente el teclado):
  • raw_input: Facilita al usuario la captura de una línea de texto. Dicha línea es devuelta por la función como una cadena de caracteres pero sin incluir el carácter final de salto de línea ('\n').
  • input: Sirve para que el usuario ingrese una secuencia de caracteres que representan una expresión válida de Python. Dicha expresión es evaluada por el intérprete y el objeto resultante es el valor devuelto por la función.
Ambas funciones reciben un prompt (mensaje de entrada) como argumento opcional.


Python 3 solamente cuenta con la función input, que realmente es equivalente en términos de comportamiento al raw_input de Python 2. Si deseamos tener en Python 3 la misma funcionalidad que el input de Python 2 entonces tenemos que utilizar adicionalmente la función eval tal como se detalla en la siguiente tabla:

Función
de Python 2
Equivalente
en Python 3
x = raw_input('Texto: ') x = input('Texto: ')
x = input('Expresión: ') x = eval(input('Expresión: '))

NOTA: El uso de la función eval se considera un riesgo de seguridad pues permite al usuario inyectar código malicioso que pudiera comprometer la integridad del sistema. En general se recomienda evitar su uso.
Para que nuestro programa funcione igual en ambas versiones de Python debemos importar la función input del módulo builtins usando la siguiente instrucción:
from builtins import input
Después de esta instrucción la función input se comporta siempre como si estuviéramos en Python 3, aún estando en Python 2. No está de más mencionar que para obtener una completa compatibilidad entre versiones es importante que dejemos de usar la función raw_input ya que no está disponible en Python 3.
NOTA: Al parecer la instrucción “from builtins import input” produce un error en varias plataformas corriendo Python 2. El mensaje de error indica que no puede hallar el módulo builtins. Para corregir este problema se necesita ejecutar la siguiente instrucción con permisos de administrador desde una terminal de línea de comando:
pip2 install future
El siguiente código es un programa que usa input y que corre sin cambios en las versiones 2 y 3:
# coding=UTF-8

from __future__ import print_function
from builtins import input

num1 = int(input('Ingresa un número entero: '))
num2 = int(input('Ingresa otro número entero: '))
if num1 == num2:
    print('Ambos números son iguales')
elif num1 > num2:
    print(num1, 'es el número más grande')
else:
    print(num2, 'es el número más grande')
Conviene señalar que para convertir la cadena de caracteres devuelta por la función input a un número podemos utilizar las funciones int o float, dependiendo de si necesitamos un número entero o un número real (de punto flotante). Lo anterior es preferible a usar la función eval, la cual es innecesaria en este contexto y potencialmente peligrosa en la páctica.

Operador de división

El operador de división (/) funciona de manera diferente en las versiones 2 y 3 de Python.
NOTA: En Python el operador de división puede ser sobrecargado por cualquier clase (como es el caso de las clases numéricas complex y Fraction). Así pues, este operador puede tener un comportamiento muy diferente al aquí descrito cuando se usa con objetos que no sean específicamente números enteros o reales.
Veamos algunos ejemplos con Python 2:
# Python 2
>>> 20 / 3
6
>>> 20 / 3.0
6.666666666666667
Aquí podemos ver que al dividir dos números enteros el resultado da un número entero (el cociente de la división sin la parte fraccionaria). Por otro lado, se obtiene un número real cuando al menos uno de los operandos de la división es un número real. Esta forma particular de realizar la división es un legado del lenguaje C que generalmente resulta sorpresivo y poco intuitivo para la gente que está aprendiendo a programar.

La división en Python 3 funciona de manera más predecible:
# Python 3
>>> 20 / 3
6.666666666666667
>>> 20 / 3.0
6.666666666666667
En este caso el operador de división siempre produce un número real como resultado sin importar si sus operandos son enteros o reales. Este comportamiento resulta más accesible para los programadores principiantes.


Para poder usar el operador de división de forma que sea compatible con Python 2 y 3 debemos importar division del módulo __future__:
from __future__ import division
La instrucción anterior garantiza que el operador de división devolverá un resultado real. El siguiente programa produce los mismos resultados en las dos versiones de Python:
# coding=UTF-8

from __future__ import print_function
from __future__ import division

print(1 / 2)   # División verdadera (true division)
print(1 // 2)  # División de piso (floor division)
La salida de este programa es:
0.5
0
El ejemplo anterior muestra también el uso del operador de división de piso (//) el cual calcula el cociente entero de la división.

Resumen de consejos de compatibilidad

Aquí está el resumen de los cuatro consejos discutidos para escribir código fuente compatible con Python 2.7 y Python 3.x:
  • Si necesitas usar caracteres que no son parte del código ASCII (caracteres con tilde, eñe, etc.) en un archivo fuente de Python, entonces guárdalo usando el formato UTF-8 y añádele el siguiente comentario en la primera o segunda línea:
    # coding=UTF-8
    
  • Utiliza print siempre como función y no como instrucción. Añade el siguiente import a tu programa para que así sea:
    from __future__ import print_function
    
  • Para que tu programa lea una cadena de caracteres desde la entrada estándar (típicamente el teclado) utiliza únicamente la función input y solo después de usar el siguiente import:
    from builtins import input
    
    Utiliza las funciones int y float si requieres convertir la cadena de entrada a un valor numérico.
  • Para que el operador de división (/) siempre produzca un resultado real, sin importar si sus operandos son reales o enteros, añade a tu programa el siguiente import:
    from __future__ import division
    
    Utiliza el operador de división de piso (//) si requieres el cociente entero como resultado de dividir un número entre otro.

24 de marzo de 2017

Formación en competencias

Desde hace algunos años el Tecnológico de Monterrey, la institución en la que laboro, ha buscado enfatizar en sus programas de estudio universitarios el desarrollo de competencias. Pero, ¿qué es exactamente una competencia? Esta es la definición que el Tecnológico está actualmente manejando[1]:
Una competencia es la integración consciente de conocimientos, habilidades, actitudes y valores que permite enfrentar con éxito situaciones tanto estructuradas como de incertidumbre y que puede implicar procesos mentales de orden superior.
Alternativamente, se puede decir de manera más sencilla que una competencia consiste en “saber hacer algo con los conocimientos aprendidos”[2].


Las siguientes son algunas características de una educación basada en competencias[3]:
  • Es un enfoque alternativo al enfoque predominante actual, el cual está basado en objetivos.
  • En lugar de enfatizar conocimientos enfatiza el desarrollo de competencias.
  • El aprendizaje deja de ser relevante exclusivamente en un marco meramente hipotético, sino que su relevancia se extiende también al mundo real.
  • Busca formar al estudiante de manera integral dentro de su contexto personal y social, y no únicamente en el aspecto profesional.
  • Va más allá de la comprensión de conceptos, abarcando también el dominio de procedimientos y el desarrollo de actitudes.
  • Requiere de una instrucción intencional y bien planeada por parte de los maestros, con el fin de brindar la mejor experiencia de aprendizaje.
En resumen, la educación basada en competencias está orientada a la formación del alumno y no solo a la transmisión de conocimientos.


Es importante no confundir el concepto de competencia con el de objetivo de aprendizaje. Por un lado, un objetivo indica qué queremos que nuestros alumnos sepan. Por otro lado, las competencias establecen la forma en que podemos tener la certeza de que efectivamente lo saben. Las competencias definen los conocimientos y habilidades que un futuro egresado podrá desempeñar de manera exitosa en el mundo real, mientras que los objetivos de aprendizaje son específicos a la instrucción de un curso en particular[4].


Según Brooks, la educación basada en competencias ofrece múltiples ventajas para los estudiantes[5]. En principio cualquier alumno puede:
  • Trabajar a su propio ritmo y en el horario que más le convenga.
  • Construir nuevos aprendizajes a partir de sus conocimientos previos.
  • Graduarse de manera más rápida y por tanto ahorrar dinero.
  • Obtener experiencia práctica del mundo real.
Por otro lado, existen algunas posibles desventajas[6]:
  • Se enfoca más a las necesidades inmediatas de los empleadores y menos en la preparación de los estudiantes para que puedan ser flexibles en un futuro incierto.
  • No es adecuado para aquellas áreas en las que resulta difícil prescribir competencias específicas o donde se requieran incorporar nuevas habilidades o conocimientos de manera extremadamente rápida.
  • Hace que el aprendizaje tome un enfoque objetivista.
  • Esta manera de aprender pudiera resultarle inadecuada a algunas personas.
Es importante también comprender la manera en que se clasifican las competencias:
  • De acuerdo a su alcance: pueden ser transversales o disciplinares.
  • De acuerdo a su ámbito o dimensión: pueden ser personales, interpersonales, sociales o profesionales.
  • De acuerdo a su ubicación en el currículo: pueden ser básicas, intermedias o terminales.
Finalmente, vale la pena comentar sobre la forma de documentar las competencias. Se sugiere redactarlas utilizando la siguiente estructura[1]:

Estructura de una competencia

Cada elemento del diagrama anterior se describe a continuación:
  • Verbo: ¿Qué hace?
  • Objeto: ¿Qué transmite?
  • Contexto o condición: ¿En qué contexto o bajo qué condiciones?
Por ejemplo, para un curso de introducción a la programación podríamos tener la siguiente competencia:
Resuelve un problema de programación a partir de un enunciado textual el cual requiera emplear una instrucción condicional if-else.
Ahora nos queda a los profesores del Tec de Monterrey el reto de aplicar efectivamente estas ideas a nuestra práctica docente cotidiana. Aún queda mucho por aprender, pero no deja de ser emocionante la expectativa de poder brindar a nuestros alumnos cada vez mejores experiencias de aprendizaje.

Profesores del área de TI del Tecnológico de Monterrey.
Reunión nacional de grupos colegiados por disciplina,
Monterrey, Nuevo León. Julio de 2015.


Referencias

  1. Vicerrectoría Académica del ITESM, Dirección de Programas Académicos. Definición y desarrollo de competencias. México, febrero, 2017.
  2. Instituto Tecnológico de Estudios Superiores de Monterrey. Diseño y desarrollo de competencias. México, 2016.
  3. Instituto Tecnológico de Estudios Superiores de Monterrey. Educación basada en competencias. México, 2015.
  4. Vasquez, Caroline. Competencies and Learning Objectives. Estados Unidos, mayo, 2011.
  5. Brooks, Ashley. 6 Benefits of Competency-Based Education that will Excite Adult Learners. Estados Unidos, abril, 2016.
  6. Bates, Tony. The strengths and weaknesses of competency-based learning in a digital age. Canadá, septiembre, 2014.