Sunteți pe pagina 1din 273

UNIVERSIDAD DE GUADALAJARA

CENTRO UNIVERSITARIO DE CIENCIAS EXACTAS E INGENIERÍAS


DEPARTAMENTO DE MATEMÁTICAS

TOPICOS
SELECTOS DE
OPTIMIZACIÓN

M.S.I. JOSÉ FRANCISCO VILLALPANDO BECERRA


Índice

Índice ............................................................................................................................................i
Nomenclatura de los archivos de las actividades ....................................................................... vi
Unidad 1 Preparándose para programar con Python ................................................................... 1

1.1 Historia de Python ....................................................................................................... 1


1.2 ¿Por qué utilizar Python? ............................................................................................................... 4
1.3 Preparando el entorno grafico para programar con Python en Windows ...................................... 6
1.3.1 Descargando los recursos: Python 3.6.2 y PyCharm 2017.1.5 para Windows ....................... 7
1.3.2 Instalación y configuración de Python ................................................................................... 9
1.3.3 Instalación y configuración de la interface gráfica de usuario (GUI) PyCharm .................. 11
1.4 Preparando el entorno de programación ...................................................................................... 21
1.4.1 Descargando los módulos gráficos y matemáticos: numpy, matplotlib y sympy ................. 22
1.4.2 Instalando numpy, matplotlib y sympy ................................................................................ 27
1.5 Modos de trabajar con Python en Windows ................................................................................ 34
1.6 Actividades a realizar ................................................................................................................... 37
Unidad 2 Fundamentos de programación en Python ................................................................. 38
2.1 Consideraciones iniciales ............................................................................................................. 38
2.2 Números ....................................................................................................................................... 41
2.2.1 Enteros .................................................................................................................................. 41
2.2.2 Reales ................................................................................................................................... 42
2.2.3 Complejos ............................................................................................................................. 43
2.3 Cadenas de caracteres .................................................................................................................. 44
2.3.1 Índices en cadenas de caracteres .......................................................................................... 47
2.4 Listas ............................................................................................................................................ 50
2.4.1 Más operaciones con listas ................................................................................................... 54
2.5 Expresiones y operadores ............................................................................................................ 55
2.5.1 Operadores aritméticos ......................................................................................................... 56
2.5.2 Operadores lógicos ............................................................................................................... 57
2.5.3 Operadores relacionales........................................................................................................ 59
2.5.4 Operadores de asignación ..................................................................................................... 60
2.5.5 Operador paréntesis y expresiones anidadas ........................................................................ 63

i
2.5.6 Orden de evaluación ............................................................................................................. 64
2.5.7 Cambiando el orden de evaluación ....................................................................................... 65
2.6 Estructura de control de flujo ....................................................................................................... 66
2.6.1 Estructura de control condicional IF .................................................................................... 66
2.6.2.1 Dos alternativas en la estructura de control condicional IF... ELSE... ......................................... 67
2.6.2.2 Sangrado de los bloques ............................................................................................................... 70
2.6.2.3 Estructuras de control condicionales anidadas ............................................................................. 72
2.6.2.4 Más de dos alternativas: IF... ELIF... ELSE... .............................................................................. 73
2.6.2.5 Casos mutuamente excluyentes .................................................................................................... 74
2.6.2.6 Casos que incluyen otros .............................................................................................................. 75
2.6.2 Estructura de control iterativa WHILE ................................................................................. 78
2.6.2.1 Ciclos infinitos ............................................................................................................................. 81
2.6.3 Estructura de control iterativa FOR ...................................................................................... 82
2.6.3.1 Ciclos FOR anidados .................................................................................................................... 86
2.6.3.2 Ciclos anidados (variables independientes) .................................................................................. 86
2.6.3.3 Ciclos anidados (variables dependientes) ..................................................................................... 87
2.7 Vectores y matrices ...................................................................................................................... 88
2.7.1 Usando la biblioteca estándar de Python .............................................................................. 88
2.7.2 Utilizando el paquete numpy ................................................................................................ 91
2.7.2.1 Operaciones con matrices ............................................................................................................. 93
2.7.2.2 Otros métodos para arreglos en numpy ........................................................................................ 96
2.7.2.3 Expansión de arreglos .................................................................................................................. 97
2.7.2.4 Leer o guardar datos de una matriz en un archivo ........................................................................ 97
2.7.3 Utilizando el paquete sympy .............................................................................................. 100
2.8 Actividades a realizar ................................................................................................................. 100
2.8.1 Programas que no utilizan estructuras de control ............................................................... 100
2.8.2 Programas que utilizan estructuras de control condicionales, pero no iterativas ............... 102
2.8.3 Programas generales, utilizando todas las estructuras de control ....................................... 105
Unidad 3 Programación de funciones ...................................................................................... 110
3.1 Definición de funciones ............................................................................................................. 110
3.2 Nombres y tipos de variables ..................................................................................................... 112
3.2.1 Conflictos de nombres de variables .................................................................................... 112
3.2.2 Conflictos de nombres de variables en Python ................................................................... 113
3.2.3 Variables locales ................................................................................................................. 114
3.2.4 Variables declaradas global o nonlocal .............................................................................. 116
 ii 
3.3 Argumentos y devolución de valores ......................................................................................... 118
3.3.1 Argumentos indeterminados ............................................................................................... 119
3.3.1.1 Argumentos por posición ........................................................................................................... 119
3.3.1.2 Argumentos por nombre............................................................................................................. 122
3.3.2 Argumentos por valor y por referencia............................................................................... 124
3.4 Funciones recursivas .................................................................................................................. 125
3.5 Generadores ............................................................................................................................... 127
3.5.1 ¿Para qué sirven y cómo se construyen los generadores? .................................................. 127
3.5.2 Utilizando generadores ....................................................................................................... 128
3.6 Funciones integradas .................................................................................................................. 131
3.7 Actividades a realizar ................................................................................................................. 141
Unidad 4 Matemática simbólica .............................................................................................. 150
4.1 Introducción al Cálculo Simbólico en Python con sympy ......................................................... 150
4.1.1 Precisión arbitraria.............................................................................................................. 150
4.1.2 Simplificación numérica ..................................................................................................... 152
4.1.3 Variables simbólicas ........................................................................................................... 153
4.2 Manipulaciones de expresiones algebraicas .............................................................................. 154
4.2.1 Sustitución .......................................................................................................................... 155
4.2.2.1 Conversión de cadenas en expresiones sympy ........................................................................... 158
4.2.2 Simplificación y expansión ................................................................................................ 158
4.2.2.1 Función simplify() ...................................................................................................................... 158
4.2.2.2 Función expand() ....................................................................................................................... 160
4.2.2.3 Función factor() .......................................................................................................................... 160
4.2.2.4 Función collect() ........................................................................................................................ 162
4.2.2.5 Función cancel() ......................................................................................................................... 162
4.2.2.6 Función apart() ........................................................................................................................... 163
4.2.3 Simplificaciones trigonométricas ....................................................................................... 163
4.2.3.1 Función trigsimp() ...................................................................................................................... 163
4.2.3.2 Función expand_trig() ................................................................................................................ 164
4.3 Cálculo ....................................................................................................................................... 165
4.3.1 Derivación .......................................................................................................................... 165
4.3.2 Integración .......................................................................................................................... 167
4.3.3 Límites ................................................................................................................................ 169
4.4 Resolución de ecuaciones .......................................................................................................... 171
4.5 Álgebra Lineal ........................................................................................................................... 174
 iii 
4.5.1 Escalares, vectores y matrices ............................................................................................ 174
4.5.2 Creando vectores y matrices ............................................................................................... 175
4.5.3 Manipulación de arreglos y matrices .................................................................................. 178
4.5.3.1 Método shape()........................................................................................................................... 179
4.5.3.2 Acceso a filas y columnas individuales ...................................................................................... 180
4.5.3.3 Eliminar e insertar filas y columnas ........................................................................................... 180
4.5.3.4 Operaciones con matrices y vectores ......................................................................................... 181
4.6 Ecuaciones diferenciales ............................................................................................................ 182
4.7 Actividades a realizar ................................................................................................................. 186
Unidad 5 Trabajando con gráficas ........................................................................................... 189
5.1 Introducción ............................................................................................................................... 189
5.2 Funciones principales de matplotlib .......................................................................................... 192
5.3 Creando una gráfica de líneas .................................................................................................... 195
5.3.1 Crear una gráfica a partir de una lista ................................................................................. 196
5.3.2 Crear una gráfica a partir de un array de numpy ................................................................ 196
5.4 Activar y desactivar el modo interactivo de dibujo ................................................................... 198
5.5 Graficando funciones personalizadas......................................................................................... 199
5.6 Añadir leyendas a las gráficas.................................................................................................... 199
5.7 Cambiar estilos de línea, marcadores y colores de una gráfica.................................................. 200
5.8 Añadir rótulos a los ejes ............................................................................................................. 202
5.9 Trabajar con varias gráficas (subplots) ...................................................................................... 203
5.10 Activar gráficas por su número o por su nombre ..................................................................... 208
5.11 Continuar "dibujando" o reiniciar la gráfica ............................................................................ 209
5.13 Guardar una gráfica.................................................................................................................. 211
5.13 Dibujar una gráfica de diferentes maneras ............................................................................... 212
5.13.1 Gráfica de barras horizontales .......................................................................................... 212
5.13.2 Gráfica de múltiples barras verticales .............................................................................. 213
5.13.3 Gráfica circular ................................................................................................................. 213
5.14 Más ejemplos de gráficas ......................................................................................................... 214
5.15 Dibujando gráficas 3D ............................................................................................................. 217
5.15 Actividades a realizar ............................................................................................................... 219
Unidad 6 Colecciones de Datos ............................................................................................... 223
6.1 Introducción ............................................................................................................................... 223
6.2 Tuplas......................................................................................................................................... 223
 iv 
6.2.1 ¿Qué no se puede hacer con las tuplas?.............................................................................. 226
6.3 Conjuntos ................................................................................................................................... 227
6.3.1 ¿Cómo crear conjuntos? ..................................................................................................... 227
6.3.2 Operaciones sobre conjuntos .............................................................................................. 229
6.4 Diccionarios ............................................................................................................................... 232
6.5 Diagramas de Venn .................................................................................................................... 237
6.6 Actividades a realizar ................................................................................................................. 239
Unidad 7 Manejo de datos por archivo .................................................................................... 244
7.1 Introducción ............................................................................................................................... 244
7.2 Abriendo un archivo .................................................................................................................. 244
7.2.1 Modos de apertura de un archivo ....................................................................................... 245
7.3 Leer datos de un archivo ............................................................................................................ 246
7.4 Escribir datos en un archivo ....................................................................................................... 247
7.4 Cerrar un archivo ....................................................................................................................... 248
7.5 Eliminar datos de un archivo ..................................................................................................... 249
7.7 Modificar datos de un archivo ................................................................................................... 250
7.8 Omitiendo el encabezado de un archivo .................................................................................... 251
7.9 Actividades a realizar ................................................................................................................. 252
Unidad 8 Errores y excepciones .............................................................................................. 255
8.1 Errores de sintaxis ...................................................................................................................... 255
8.2 Excepciones ............................................................................................................................... 255
8.3 Manejo de excepciones .............................................................................................................. 256
8.4 Levantando excepciones ............................................................................................................ 259
8.5 Cláusula finally .......................................................................................................................... 260
8.6 Excepciones disponibles ............................................................................................................ 261
8.7 Actividades a realizar ................................................................................................................. 263
Trabajo final ............................................................................................................................ 264

v
Nomenclatura de los archivos de las actividades
Para la unidad 1, la actividad deberá ser elaborada en MicroSoft Word®, siguiendo las
indicaciones de entrega de dicha actividad. De las unidades 2 a la 8 se realizarán los programas
correspondientes a cada actividad y se entregarán en la fecha indicada. No se admitirá ninguna
actividad fuera de la fecha señalada.
Los nombres de los archivos o programas de las actividades deberán seguir la nomenclatura
mencionada a continuación:
a) Para la unidad 1: act01.docx
Ya que es la única actividad de la unidad.
b) Para la unidad 2: act02_yz.py
donde: y el número del ejercicio de la actividad, z es el inciso y py es la extensión de los archivos
de Python. Por ejemplo act02_3g.py, corresponde al programa del inciso g, de la actividad 3 de
la unidad 2.
c) Para las unidades 3 a la 8: actxx_y.py
donde: xx es el número de la unidad, y es el inciso y py es la extensión de los archivos de Python.
Por ejemplo act05_b.py, corresponde al programa del inciso b, de la unidad 5.
Adicionalmente cada programa .py deberá contener el nombre, código y sección del alumno, el
cual deberá ser mostrado en la pantalla al momento de ejecutarlo.
Todos los programas de cada actividad deberán ser compactados en un sólo archivo en formato
.zip o .rar y enviados por e-mail a la dirección indicada por el profesor. En el asunto o subject del
e-mail se deberá incluir la palabra Topicos, nombre del alumno y sección. Por ejemplo: Topicos,
Juan Pérez, D03.
Si alguna actividad incumple con estos requisitos no será tomada en cuenta.

 vi 
Unidad 1 Preparándose para programar con Python

1.1 Historia de Python

El origen del lenguaje Python se remonta a principios de los noventa. Por este tiempo, un
investigador holandés llamado Guido van Rossum, que trabajaba en el centro de investigación CWI
(Centrum Wiskunde & Informatica) de Ámsterdam, es asignado a un proyecto que consistía en el
desarrollo de un sistema operativo distribuido llamado Amoeba. Por aquel tiempo, el CWI utilizaba
un lenguaje de programación llamado ABC. En lugar de emplear este lenguaje para el proyecto
Amoeba, Guido decide crear uno nuevo que pueda superar las limitaciones y problemas con los
que se había encontrado al trabajar en otros proyectos con ABC. Así pues, es esta la principal
motivación que dio lugar al nacimiento de Python.
La primera versión del lenguaje ve la luz en 1991, pero no es hasta tres años después cuando
decide publicarse la versión 1.0. Inicialmente el CWI decidió liberar el intérprete del lenguaje bajo
una licencia Open Source propia, pero en septiembre de 2000 y coincidiendo con la publicación de
la versión 1.6, se toma la decisión de cambiar la licencia por una que sea compatible con la licencia
GPL (GNU General Public Licence). Esta nueva licencia se denominó Python Software Foundation
Licence y se diferencia de la GPL al ser una licencia no Copyleft. Este hecho implica que es posible
modificar el código fuente y desarrollar código derivado sin la necesidad de hacerlo Open Source.
Hasta el momento solo se han liberado tres versiones principales, teniendo cada una de ellas
diversas actualizaciones. En lo que respecta a la versión 2, la última en ser liberada fue la 2.7, en
julio de 2010. Actualmente, la versión 3 cuenta con la actualización 3.6.2, liberada el 17 de julio
de 2017. Ambas versiones (2 y 3), son mantenidas por separado. Esto implica, que tanto la 2.7
como la 3.6.2 se consideran estables pero, lógicamente, correspondientes a diferentes versiones.
¿Por qué mantener ambas versiones y no seguir una evolución lógica? La respuesta a esta pregunta
es fácil de responder: entre ambas versiones existen diferencias que las hacen incompatibles.
Entre las características de las primeras versiones de Python cabe destacar el soporte de la
orientación a objetos, el manejo de excepciones y el soporte de estructuras de datos de alto nivel,
como, por ejemplo, las listas y los diccionarios. Además, desde su desarrollo inicial, se tuvo en
cuenta que el código escrito en este lenguaje fuera fácil de leer y de aprender, sin que esto suponga
renunciar a características y funcionalidades avanzadas.

1
Muchos se preguntan el origen del nombre de Python. Gudo van Rossum decidió darle este
nombre en honor a la serie de televisión Monty Python's Flying Circus, de la cual era fan. Esta es
una serie cómica protagonizada por el grupo de humoristas Monty Python, famoso por películas
como La vida de Brian o El sentido de la vida. Desde el principio de su diseño, se pretendía que
Python fuera un lenguaje que resultara divertido de utilizar, de ahí que en el nombre influyera la
mencionada serie cómica. También resulta curioso que, tanto en tutoriales, como en ejemplos de
código, se suelen utilizar referencias a los Monty Python. Por ejemplo, en lugar de emplear los
tradicionales nombres de variables foo y bar, se suele utilizar spam y egss, en referencia a sketchs
de este grupo de cómicos.
El desarrollo y promoción de Python se lleva a cabo a través de una organización, sin ánimo de
lucro, llamada Python Software Foundation, que fue creada en marzo de 2001. Entre las actividades
que realiza esta organización destacan el desarrollo y distribución oficial de Python, la gestión de
la propiedad intelectual del código y documentos realizados, así como la organización de
conferencias y eventos dedicados a poner en contacto a todas aquellas personas interesadas en este
lenguaje de programación.
Python tiene claro carácter Open Source y la Python Software Foundation invita, a cualquiera
que quiera hacerlo, a contribuir al desarrollo y promoción de este lenguaje de programación.
Las versiones de Python se identifican por tres números X.Y.Z, en la que:
 X corresponde a las grandes versiones de Python (1, 2 y 3), incompatibles entre sí. Los
principales cambios introducidos en Python 2 fueron las cadenas Unicode, las comprensiones
de listas, las asignaciones aumentadas, los nuevos métodos de cadenas y el recolector de basura
para referencias cíclicas. Los principales cambios introducidos en Python 3 fueron la separación
entre cadenas Unicode y datos binarios, la función print(), cambios en la sintaxis, tipos de datos,
comparadores, etc. Por el momento, no hay planes de crear una nueva versión Python 4,
incompatible con las anteriores.
 Y corresponde a versiones importantes en las que se introducen novedades en el lenguaje pero
manteniendo la compatibilidad (salvo excepciones). Desde hace unos años, las versiones X.Y
se publican aproximadamente cada año y medio y se mantienen durante cinco años, excepto la
versión 2.7, que se mantendrá por lo menos durante diez años, hasta 2020.
 Z corresponde a versiones menores que se publican durante el período de mantenimiento, en las
que sólo se corrigen errores y fallos de seguridad.

2
Normalmente, se publica una última versión X.Y.Z justo antes de que una versión X.Y deje de
mantenerse. Algunas empresas comerciales ofrecen el mantenimiento de versiones antiguas una
vez acabado el mantenimiento oficial.
En la figura 1.1 se muestra la fecha de publicación de las versiones importantes de Python, en
cada una de las tres grandes versiones, Python 1, Python 2 y Python 3. Las versiones indicadas con
punto rojo se consideran obsoletas, las versiones indicadas con punto negro siguen publicando
actualizaciones, las versiones indicadas con punto blanco corresponden a versiones futuras con
fechas ya previstas.

Figura 1.1 Versiones importantes de Python


La figura 1.2 muestra la fecha de publicación de las últimas versiones menores de Python. Las
versiones indicadas en rojo se consideran obsoletas, las versiones indicadas con punto blanco
corresponden a versiones futuras con fechas ya previstas.

Figura 1.2 Versiones menores de Python

3
1.2 ¿Por qué utilizar Python?

Python es un lenguaje de programación poderoso y fácil de aprender. Cuenta con estructuras de


datos eficientes y de alto nivel y un enfoque simple pero efectivo a la programación orientada a
objetos. La elegante sintaxis de Python y su tipado dinámico, junto con su naturaleza interpretada,
hacen de éste un lenguaje ideal para scripting y desarrollo rápido de aplicaciones en diversas áreas
y sobre la mayoría de las plataformas.
El intérprete de Python y la extensa biblioteca estándar están a libre disposición en forma binaria
y de código fuente para las principales plataformas desde el sitio web de Python,
https://www.python.org/, y puede distribuirse libremente. El mismo sitio contiene también
distribuciones y enlaces de muchos módulos libres de Python de terceros, programas y
herramientas, y documentación adicional.
El intérprete de Python puede extenderse fácilmente con nuevas funcionalidades y tipos de datos
implementados en C o C++ (u otros lenguajes accesibles desde C). Python también puede usarse
como un lenguaje de extensiones para aplicaciones personalizables.
Este manual introduce de manera informal al lector a los conceptos y características básicas del
lenguaje y el sistema de Python. Es bueno tener un intérprete de Python a mano para experimentar,
sin embargo todos los ejemplos están aislados, por lo tanto el manual puede leerse estando
desconectado.
Para una descripción de los objetos y módulos estándar, ver La referencia de la biblioteca
(https://docs.python.org/3/library/index.html). La referencia de la biblioteca provee una definición
más formal del lenguaje. Para escribir extensiones en C o C++, leer Extendiendo e Integrando el
Intérprete de Python (https://docs.python.org/3/extending/index.html) y la Referencia de la API
Python/C (https://docs.python.org/3/c-api/index.html). Hay también numerosos libros que tratan a
Python en profundidad.
Este manual no pretende ser exhaustivo ni tratar cada una de las características, o siquiera las
características más usadas. En cambio, introduce la mayoría de las características más notables de
Python, y eso dará una buena idea del gusto y estilo del lenguaje. Luego de leerlo, se podrán leer y
escribir módulos y programas en Python, y se estará listo para aprender más de los variados
módulos de la biblioteca de Python descriptos en La referencia de la biblioteca.
Si se trabaja con computadoras, eventualmente se encontrará el gusto por automatizar algunas
tareas. Por ejemplo, realizar una búsqueda y reemplazo en un gran número de archivos de texto, o

4
renombrar y reorganizar un montón de archivos con fotos de una manera compleja. Tal vez escribir
alguna pequeña base de datos personalizada, o una aplicación especializada con interfaz gráfica, o
un juego simple.
Si se es un desarrollador de software, tal vez se necesite trabajar con varias bibliotecas de
C/C++/Java o Fortran pero esto hace lento el ciclo usual de escribir/compilar/probar/recompilar.
Tal vez se está escribiendo varias pruebas para una de esas bibliotecas y se encuentra que escribir
el código de prueba se hace una tarea tediosa. O tal vez se ha escrito un programa al que le vendría
bien un lenguaje de extensión, y no se quiere diseñar/implementar todo un nuevo lenguaje para
dicha aplicación. En cualquiera de los dos casos Python es el lenguaje justo para ese tipo de
actividades.
Se podrá escribir un script (o programa) en el intérprete de comandos o un archivo por lotes de
Windows para algunas de estas tareas, pero los scripts se lucen para mover archivos de un lado a
otro y para modificar datos de texto, no para aplicaciones con interfaz de usuario o juegos. Se
podría escribir un programa en C/C++/Java o Fortran, pero puede tomar mucho tiempo de
desarrollo obtener al menos un primer borrador del programa. Python es más fácil de usar, está
disponible para sistemas operativos Windows, Mac OS X y Unix, y ayudará a realizar esa tarea
más rápidamente.
Es fácil de usar, pero es un lenguaje de programación de verdad, pues ofrece mucha más
estructura y soporte para programas grandes de lo que pueden ofrecer los scripts de Unix o archivos
por lotes en Windows. Por otro lado, Python ofrece mucho más chequeo de error que C, y siendo
un lenguaje de muy alto nivel, tiene tipos de datos de alto nivel incorporados como arreglos de
tamaño flexible y diccionarios. Debido a sus tipos de datos más generales Python puede aplicarse
a un dominio de problemas mayor que Awk (lenguaje de programación diseñado para procesar
datos basados en texto, ya sean archivos o flujos de datos) o incluso Perl (lenguaje de programación
diseñado por Larry Wall en 1987. Perl toma características del lenguaje C, del lenguaje interpretado
bourne shell (sh), Awk, sed, Lisp y, en un grado inferior, de muchos otros lenguajes de
programación.), y aun así muchas cosas siguen siendo al menos igual de fácil en Python que en
esos lenguajes.
Este lenguaje de programación permite separar un programa en módulos que pueden reusarse
en otros programas en Python. Viene con una gran colección de módulos estándar que se pueden
usar como base de en los programas, o como ejemplos para empezar a aprender a programar en

5
Python. Algunos de estos módulos proveen cosas como entrada/salida a archivos, llamadas al
sistema, sockets, e incluso interfaces a sistemas de interfaz gráfica de usuario como Tk.
Es un lenguaje interpretado, lo cual puede ahorrarte mucho tiempo durante el desarrollo ya que
no es necesario compilar ni enlazar. El intérprete puede usarse interactivamente, lo que facilita
experimentar con características del lenguaje, escribir programas descartables, o probar funciones
cuando se hace desarrollo de programas de abajo hacia arriba. Es también una calculadora de
escritorio práctica.
Permite escribir programas compactos y legibles. Los programas en Python son típicamente más
cortos que sus programas equivalentes en C, C++ o Java o incluso que Fortran por varios motivos:
• Los tipos de datos de alto nivel permiten expresar operaciones complejas en una sola
instrucción.
• La agrupación de instrucciones se hace por sangría en vez de llaves de apertura y cierre.
• No es necesario declarar variables ni argumentos.
Python es extensible: si ya se ha programado, por ejemplo en C o Fortran, es fácil agregar una
nueva función o módulo al intérprete, ya sea para realizar operaciones críticas a velocidad máxima,
o para enlazar programas Python con bibliotecas que tal vez sólo estén disponibles en forma binaria
(por ejemplo bibliotecas gráficas específicas de un fabricante).

1.3 Preparando el entorno grafico para programar con Python en Windows

Como se mencionó, la versión 3 de Python cuenta con la actualización 3.6.2, liberada el 17 de


julio de 2017, siendo su modo nativo de trabajo por línea de comandos, por lo que es necesario
instalar algún software de terceros para programar en un entorno gráfico más amigable, esto es, por
medio de una GUI (Interface Gráfica de Usuario, por sus siglas en inglés).
Para ello existe gran cantidad de programas que cubren esa función, algunos más amigables que
otros. Se eligió PyCharm como GUI ya que entre otras cosas cuenta con un entorno de desarrollo
integrado, en inglés Integrated Development Environment (IDE), es decir, es una aplicación
informática que proporciona servicios integrales para facilitarle al desarrollador o programador el
desarrollo de software. Normalmente, un IDE consiste de un editor de código fuente, herramientas
de construcción automáticas y un depurador. La mayoría de los IDE tienen auto-completado
inteligente de código (IntelliSense), tal como es el caso de PyCharm.

6
El límite entre un IDE y otras partes del entorno de desarrollo de software más amplio no está
bien definido. Muchas veces, a los efectos de simplificar la construcción de la GUI, se integran un
sistema controlador de versión y varias herramientas.

1.3.1 Descargando los recursos: Python 3.6.2 y PyCharm 2017.1.5 para Windows
Para programar en Python, primero es necesario descargar su intérprete, en este caso para
Windows, lo cual se puede hacer de forma gratuita desde el sitio web de Python
http://wwwpython.org (figura 1.3). Desde dicho sitio se puede descargar la versión y actualización
más reciente de Python, hay que recordar que es la 3.6.2, o si se requiere, por algún motivo, alguna
anterior también es posible hacerlo. Además, en el mismo sitio, es posible descargar
documentación diversa de Python, la cual se encuentra exclusivamente en inglés.
Al seleccionar Downloads for Windows, por default se mostrará la versión 3.6.2 y la 2.7.13
(figura 1.4), ya se había mencionado el por qué se sigue utilizando esta última versión. Si se tiene
una computadora con Windows XP o anterior, no será posible utilizar las versiones más recientes
de Python. En dicho caso deberá descargarse una versión anterior a la 3.5.

Figura 1.3 Página principal de Python Figura 1.4 Descarga de Python 3.6.2
Existe un sitio web en el cual se han dado a la tarea de traducir al español la mayoría de los
documentos que se localizan en el sitio oficial de Python, dicho sitio tiene la dirección
http://www.python.org.ar/ (Figura 1.5). También hay un sitio web de Python en México
(http://python.org.mx/), el mismo está en proceso de construcción.

7
Figura 1.5 Sitio con la documentación de Python es español
Ya que se tiene descargado el intérprete de Python, será necesario descarga el IDE con el GUI
seleccionado para programar en un ambiente gráfico. Como se mencionó, en este caso será
PyCharm, el cual es posible descargarlo de forma gratuita desde su sitio oficial, el cual es
https://www.jetbrains.com/PyCharm/ (figura 1.6). Basta con hacer clic la opción de download
now.
Posteriormente se mostrará la pantalla presentada en la figura 1.7, en la cual hay dos opciones
para descargar PyCharm para Windows, que es la selección por default, la primera es la descarga
de la versión de prueba Profesional de PyCharm. La segunda es la versión gratuita Community.
Esta segunda opción es la que se procederá a descargar y con la que se estará trabajando a lo
largo del manual.

Figura 1.6 Página principal de PyCharm Figura 1.7 Descargando PyCharm

8
1.3.2 Instalación y configuración de Python
Para instalar Python 3.6.2 en un equipo con el sistema operativo Windows 7, 8, 8.1 o 10 será
necesario utilizar una cuenta de usuario con privilegios de administrador, o bien, la propia cuenta
del administrador local. Por seguridad, se puede agregar, temporalmente, para este proceso de
instalación la cuenta del usuario actual al grupo local Administradores. Para ello, iniciar la
aplicación de Administración de equipos, acceder a la herramienta del sistema Usuarios y grupos
locales y agregar la cuenta actual a dicho grupo.
En los sistemas con arquitectura 64 bit se puede instalar tanto la versión de Python para 32 bit
como para 64 bit. En general, trabajar con la versión para 64 bit mejora el rendimiento y permite
que un programa pueda utilizar más de 4 Gb de RAM, memoria límite en sistemas 32 bit.
Normalmente, trabajando por debajo de este límite no se observan diferencias de rendimiento
importantes entre ambas versiones pero se recomienda instalar la versión de 64 bit. De todas
formas, si se van a utilizar módulos de terceros, conviene comprobar si están disponibles para la
versión a instalar.
Para instalar Python 3.6.2 se deberán seguir pasos mencionados a continuación:
Lo primero que se tiene que hacer es buscar el instalador de Python que, por default, al
descargarlo queda ubicado en la carpeta Descargas o Downlods. El icono de dicho instalador es el
mostrado en la figura 1.8. Una vez que se ha localizado se hace doble clic sobre el mismo, con lo
que se inicia el proceso de instalación. Si es necesario, confirmar la ejecución en la ventana de
advertencia de seguridad de Control de cuentas de usuario (figura 1.9), para permitir que se instale
Python.

Figura 1.8 Icono del Instalador de Python 3.6.2 Figura 1.9 Control de cuentas de usuario
Una vez iniciado el instalador, en la ventana Install Python 3.6.2 (figura 1.10) activar las casillas
de las opciones: Install launcher for all users (recommended) y Add Python 3.6 to PATH (figura

9
1.11). Después, continuar seleccionando la opción Customize installation. Choose Location and
features. En caso no que querer continuar con la instalación hacer clic en el botón .

Figura 1.10 Iniciando la instalación Figura 1.11 Incluyendo ruta de Python


En la ventana Optional features verificar que están activas todas las opciones y luego hacer clic
en el botón (figura 1.12). En caso de querer regresar a la ventana anterior hacer clic en el
botón .
Posteriormente se mostrará la ventana Advanced Options (figura 1.13).

Figura 1.12 Características opcionales Figura 1.13 Opciones avanzadas


A continuación se debe verificar que estén activas las opciones Install for all users y Precompile
standar library, si se tiene internet en el momento se puede activar la casilla Download debugging
symbols (figura 1.14). Luego se muestra la localización donde se instalará Python C:\Program Files
(x86)\Python36-32, si se quiere instalar en dicha ruta por defecto hacer clic en el botón o
si se quiere en un la ruta diferente a la del directorio de instalación hacer clic en y
seleccionar el directorio en que se quiera realizar la instalación. Posteriormente para comenzar la
instalación se hace clic en el botón . Después de unos segundos de espera, comenzará la
instalación de Python (figura 1.15).

 10 
Figura 1.14 Seleccionado opciones avanzadas Figura 1.15 Instalando Python

Finalmente se mostrará la ventana de Setup was successful, la cual indica que se ha instalado
Python satisfactoriamente (figura 1.16). Solamente resta hacer clic en el botón y listo ya
se tiene Python instalado.
En la figura 1.17 se muestra que Python es un nuevo programa instalado en el sistema operativo
Windows, por lo que ya es posible utilizarlo, la forma de trabajar recién instalado Python se
mencionará en el tema 1.5.

Figura 1.16 Finalizando instalación Figura 1.17 Ubicación de Python

1.3.3 Instalación y configuración de la interface gráfica de usuario (GUI) PyCharm


Ahora se procederá a instalar el GUI PyCharm, el cual cuenta con un debugger incorporado, lo que
ayuda mucho a la hora de encontrar errores cuando se está programando.
Lo primero que se tiene que hacer es buscar el instalador de PyCharm que, por default, también
al descargarlo queda ubicado en la carpeta Descargas o Downlods. El icono de dicho instalador es
el mostrado en la figura 1.18. Una vez que se ha localizado se hace doble clic sobre el mismo, con
lo que se inicia el proceso de carga del instalador (figura 1.19).

 11 
Figura 1.18 Icono del Instalador de PyCharm Figura 1.19 Cargando el instalador de PyCharm
Si es necesario, confirmar la ejecución en la ventana de advertencia de seguridad de Control de
cuentas de usuario (figura 1.20), para permitir que se instale PyCharm. Enseguida se mostrará la
bienvenida al instalador de PyCharm (figura 1.21), en donde se indica que se cierren todas las
aplicaciones antes de iniciar con la instalación. A continuación se debe hacer clic en el botón
para continuar con el proceso de instalación. Si no se quiere continuar con la instalación
hacer clic en el botón .

Figura 1.20 Control de cuentas de usuario Figura 1.21 Bienvenida al Setup de PyCharm
Luego en la ventana Chosse Install Location (figura 1.22) se muestra la localización donde se
instalará PyCharm C:\Program Files\JetBrains\PyCharm Community Edition 2017.1.5, si se quiere
instalar en dicha ruta por defecto hacer clic en el botón o si se quiere en un la ruta diferente
a la del directorio de instalación hacer clic en y seleccionar el directorio en que se quiera.
Posteriormente para comenzar la instalación se hace clic en el botón .
En la ventana Install Options se pregunta si se quiere crear un acceso directo en el escritorio,
ya sea para 32 o 64 bits, y además si se pretende asociar los archivos .py (figura 1.23). Se
recomienda seleccionar las 2 opciones (figura 1.24), ya que se creará un acceso directo en el
escritorio y además asocia todos los ficheros .py a esta aplicación. De este modo en un futuro no
se tendrá que seleccionar el IDE predefinido para los archivos de Python, pero no es obligatorio
hacerlo ahora ya que en un futuro se puede hacer igualmente.

 12 
Figura 1.22 Directorio de instalación Figura 1.23 Opciones de instalación
Enseguida hacer clic en el botón , para seguir con el proceso de instalación,
para regresar a la ventana anterior o si no se quiere cancelar con la instalación.
Después en la ventana Choose Star Menu Folder, se selecciona la carpeta en la cual se creará
el acceso rápido para PyCharm (figura 1.25), por lo default es JetBrains, pero se puede seleccionar
otro nombre si se desea. Luego hacer clic en el botón .

Figura 1.24 Opciones de instalación seleccionadas Figura 1.25 Carpeta de acceso rápido
Después de unos segundos de espera, comenzará la instalación de PyCharm (figura 1.26).
Cuando la misma haya terminado se mostrará la ventana Completing PyCharm Community
Edition Setup, si se quiere ejecutar el programa se selecciona la opción Run PyCharm Community
Edition y se da clic en el botón , sino solamente se da clic a dicho botón para terminar todo
el proceso de instalación (figura 1.27).

 13 
Figura 1.26 Instalando PyCharm Figura 1.27 Finalizando la instalación de
PyCharm
En la figura 1.28 se muestra que PyCharm es un nuevo programa instalado en el sistema
operativo Windows, por lo que ya es posible utilizarlo, así que si se hace clic en JetBrains
PyCharm Community, se ejecutará PyCharm y se mostrará la ventana Complete Installation
(figura 1.29), entonces se selecciona la opción de Do not import settings, ya que es la primera vez
que se instala el programa. Enseguida se da clic en el botón para iniciar con la carga de
PyCharm Community 2017.1 (figura 1.30).

Figura 1.28 Ubicación de PyCharm Figura 1.29


Una vez que termina de cargarse PyCharm se mostrará la ventana de Welcome PyCharm
Community Edition, en la cual se solicita si se quiere crear un proyecto o abrir uno ya existente
(figura 1.31). Haga lo que se haga en PyCharm, se realiza en el contexto de un proyecto. Un
proyecto es una unidad organizativa que representa una solución completa de software. Sirve de
base para el asistente de codificación, codificación de la consistencia del estilo, etc.
Un proyecto en PyCharm está representado en el formato basado en un directorio. El directorio
de un proyecto está siempre marcado con el icono . Por lo que si no hay ningún proyecto creado
se debe crear uno al menos.

 14 
Figura 1.30 Cargando PyCharm Figura 1.31 Bienvenida a PyCharm
Antes de iniciar con un proyecto se muestra la ventana de PyCharm Community Edition Initial
Configuration (figura 1.32), es recomendable dejar las opciones por defecto y hacer clic en el
botón .
Por default se creará un proyecto en la carpeta c:\user\usuario\PyCharmProyects\ (figura 1.33),
pero es recomendable seleccionar otra carpeta donde crear el proyecto. Enseguida hacer clic en el
botón . Al mismo tiempo que se pretende crear un proyecto, se actualiza el intérprete de
Python.

Figura 1.32 Configuración inicial Figura 1.33 Creando un proyecto y actualizando el


intérprete de Python
Cuando se crea un proyecto, siempre se crea la carpeta .idea como carpeta raíz del mismo,
contiene los archivos de configuración específicos del proyecto de IntelliJ (figura 1.32). Estos
incluyen detalles del proyecto, como mapeo de VCS y configuraciones de ejecución y depuración,
así como detalles por usuario, como archivos abiertos actualmente, historial de navegación y
configuración seleccionada actualmente.

 15 
Si se pretende abrir un proyecto, por default en la primera ocasión, se hará en la carpeta
c:\user\usuario\ (figura 1.34). También se puede abrir directamente un archivo de Python de un
proyecto existente (figura 1.35) o el mismo hacer clic en la misma carpeta .idea (figura 1.36).

Figura 1.34 Abriendo un Figura 1.35 Abriendo un Figura 1.36 Abriendo un


proyecto por primera vez archivo Python proyecto existente
Cuando se muestra la ventana de Open Proyect (figura 1.37), se pregunta se quiere abrir el
mismo en una nueva ventana o en la actual, ya sea cual sea la elección seleccionarla y dar clic en
el botón . Posteriormente PyCharm procederá a cargar el proyecto seleccionado (figura 1.38).

Figura 1.37 Ventana de apertura del Figura 1.38 Cargando el proyecto


proyecto
Al finalizar la carga del proyecto o al terminar la ejecución de la carga de PyCharm, siempre se
mostrará la ventana Tip of the Day (figura 1.39), a menos que se desmarque la opción Show Tips
on Startup, en la cual se presentará un Tip diferente sobre el uso del PyCharm.
Si se quiere recordar algún tip ya visto con anterioridad, se puede mostrar haciendo clic en el
botón , pero si se quiere ver algún otro, se podrá hacer dando clic en el botón .
Si ya no se pretende ver ningún otro tip, dar clic en el botón .
Cuando se quiere crear un archivo nuevo, ya sa en un proyecto existente o en un nuevo proyecto
se mostrará la ventana New File (figura 1.40), se da el nombre del archivo y se hace clic en el botón
.

 16 
Figura 1.39 Mostrando el Tip del día Figura 1.40 Creando un archivo nuevo
En estos momentos se podría iniciar a programar en Python utilizando PyCharm (figura 1.41),
pues el ambiente gráfico ya está instalado.

Figura 1.41 Escribiendo un programa


Pero si es la primera ocasión que se ejecuta PyCharm, pudiera aparecer el mensaje No Python
interpreter configured for the proyect (figura 1.42).

Figura 1.42 Mensaje: no hay intérprete de Python configurado para este proyecto

 17 
Después de dicho mensaje se desactivarían las opciones de ejecución del intérprete (figura 1.43)
y no sería posible ejecutar ningún programa. Para configurar el intérprete de Python para el
proyecto actual se da clic en Configure Python Interpreter.

Figura 1.43 Acciones de ejecución desactivadas


Configurar el intérprete de Python es, en la ventana Settings, indicar a PyCharm la ubicación
del intérprete de Python, que en este caso es C:\Program Files (x86)\Python36-32. Finalmente se
hace clic en el botón .

Figura 1.44 Configurando el intérprete de Python para el proyecto


Existe otra manera de configurar el intérprete de Python, ya que se pudiera dar el caso que se
tuvieran diferentes versiones de Python para diferentes proyectos, por lo que se tendrá que cambia
de versión en cada proyecto.
En el menú de PyCharm se hace clic en la opción File y después en Settings (figura 1.45), con
lo que se muestra también la ventana de Settings y se puede seleccionar la versión requerida.

 18 
Figura 1.45 Seleccionado la opción de Settings en PyCharm
Una vez que se configuro correctamente la versión del intérprete de Python se vuelven a activar
las opciones de ejecución, con lo que ya es posible correr cualquier programa realizado (figura
1.46).

Figura 1.46 Opciones de ejecución activadas


Cuando se tienen cerrados todos los archivos de un proyecto o cuando todavía no se tienen
archivos en un nuevo proyecto se muestra una ventana como la de la figura 1.47, en la misma se
puede buscar o abrir un archivo hecho en Python. Hay que recordar que todos los archivos
elaborados en Python tienen la extensión .py.

 19 
Figura 1.47 Opciones para abrir o buscar archivos
Posiblemente en alguna ocasión, cuando se habrá PyCharm, aparezca una leyenda como la
mostrada en la figura 1.48, esto es indicativo de que existe una nueva versión del mismo. Si se
quiere actualizar a la nueva versión se PyCharm Community Edition, entonces se hace clic sobre
la liga Update.

Figura 1.48 Actualización existente de PyCharm


Enseguida se mostrará una ventana como la de la figura 1.49, en ella hay varias opciones:
 Si se hace clic sobre el botón , entonces se procederá de inmediato a la
descarga de la actualización (figura 1.50) y terminando la misma se reiniciara y volverá
a cargar PyCharm con la nueva versión (figura 1.51), que como se observa es un poco
diferente a la ventana de carga de la versión anterior (figura 1.30).
 Si se hace clic sobre el botón , no se descargará la actualización ni volverá a
aparecer el mensaje de que existe una actualización de PyCharm.

 20 
 Si se hace clic sobre el botón , de momento no se instalará la actualización,
pero cuando se vuelva a iniciar PyCharm, de nueva cuenta se mostrará el mensaje de
que existe una actualización.

Figura 1.49 Opciones de actualización Figura 1.50 Descargando la actualización


Finalmente, cuando se quiere salir de PyCharm se muestra la ventana de Confirm Exit (figura
1.52), en la cual si se hace clic sobre el botón se saldrá del programa. Pero si se hace clic
sobre el botón se cancelará la confirmación de la salida y se regresa a PyCharm.

Figura 1.51 Reiniciando PyCharm con la nueva Figura 1.52 Saliendo de PyCharm
versión después de haber sido actualizado

1.4 Preparando el entorno de programación

Una vez que se han descargado tanto el intérprete de Python con la GUI PyCharm Community
Edition, será posible crear y ejecutar programas sencillos en Python 3.6.2, pero hay un pequeño
inconveniente, no será posible correr programas que requieran ciertas funciones matemáticas como
las logarítmicas y las trigonométricas, ni tampoco aquellos que necesiten graficarse o trabajar de
forma simbólica.

 21 
Para hacer esto es necesario descargar e instalar ciertos módulos o paquetes de Python. A
continuación se mostrarán cuáles son y cómo descargarlos y posteriormente cómo instalarlos.

1.4.1 Descargando los módulos gráficos y matemáticos: numpy, matplotlib y sympy


Los módulos numpay, matplotlib y sympy proporcionan más del 90% de los requerimientos
necesarios para poder hacer un programa que requiera de manipulación o cálculo matemático.
numpy es una extensión de Python, que le agrega mayor soporte para vectores y matrices,
constituyendo una biblioteca de funciones matemáticas de alto nivel para operar con esos vectores
o matrices. Además es el encargado de añadir toda la capacidad matemática y vectorial a Python
haciendo posible operar con cualquier dato numérico o array (posteriormente se verá qué es un
array).
Incorpora operaciones tan básicas como la suma o la multiplicación u otras mucho más
complejas como la transformada de Fourier o el álgebra lineal. Además contiene herramientas que
permiten incorporar código fuente de otros lenguajes de programación como C/C++ o Fortran lo
que incrementa notablemente su compatibilidad e implementación.
Para descargar numpy es necesario ingresar a la página oficial de Python (figura 1.53) y hacer
clic en la opción PyPI (Python Package Index), que no es más que un repositorio de software
especializado para el lenguaje de programación Python. Además es la web con el repositorio oficial
para los proyectos de la comunidad Python mantenida por la Python Software Foundation. PyPI
está abierto a todos los desarrolladores de Python que deseen compartir sus proyectos, en forma de
paquetes de distribución, con otras personas. En la página de PyPI, en la opción search escribir
numpy (figura 1.54) y hacer clic en dicha opción.

Figura 1.53 Seleccionado PyPI Figura 1.54 Buscando numpy en la página de PyPI

 22 
A continuación se mostrará una ventana (figura 1.55) en la cual se verán los resultados obtenidos
en la búsqueda de numpy. Se muestran varios resultados, pero hay que hacer clic en el primer
resultado obtenido, es decir, numpy 1.13.1, que hasta el momento es su última versión.

Figura 1.55 Resultados de la búsqueda numpy


Enseguida se muestra una ventana como la de la figura 1.56, en la cual se observa en qué
plataformas puede instalarse numpy. Se debe seleccionar la liga numpy-1.13.1-cp36-none-
win32.whl.

Figura 1.56 numpy para diferentes plataformas


Como se ve, dicho archivo tiene una extensión .whl. Esto significa que un archivo de
distribución de un paquete en formato wheel.
Los paquetes wheel tienen un formato de distribución pre-built (de tipo binario) que ofrecen una
instalación más rápida en comparación con el formato del paquete source o sdist (distribución de
código fuente).
Un archivo wheel es un archivo con el formato ZIP que utiliza un nombre de archivo con una
nomenclatura que incluye el nombre del proyecto, su versión y que tiene la extensión .whl.
En este formato muchos paquetes se instalan correctamente en el momento de ser
desempaquetados ganándose velocidad en el proceso.
Entonces una vez que se descargó dicho archivo quedará en un archivo de distribución como el
mostrado en la figura 1.57.

 23 
Figura 1.57 Archivo de distribución de numpy
matplotlib es una biblioteca para la generación de gráficos a partir de datos contenidos en listas
o arrays en el lenguaje de programación Python. Proporciona una API, pylab, diseñada para
recordar la de Matlab.
Es cierto que matplotlib se basó en Matlab pero específicamente en su facilidad de uso.
matplotlib no trata de ser un reemplazo a Matlab como si lo es Octave. matplotlib es una librería
para Python que permite realizar gráficas brindando múltiples facilidades para lograr ese objetivo.
Si se requiere realizar gráficas de cualquier tipo y no se necesitan toda la cantidad de toolboxes que
vienen con Matlab, matplotlib es justo lo que se necesita.
Por otro lado, y no menos importante, matplotlib es una librería libre lo cual quiere decir entre
otras cosas que se puede usar completamente gratis, lo cual es una ventaja de entrada frente a
Matlab.
Para descargar matplotlib nuevamente es necesario ir a la página de PyPI, en la opción search
escribir matplotlib (figura 1.58) y hacer clic en dicha opción.

Figura 1.58 Buscando matplotlib en la página de PyPI


A continuación se mostrará una ventana (figura 1.59) en la cual se verán los resultados obtenidos
en la búsqueda de matplotlib. Se muestran varios resultados, pero hay que hacer clic en el primer
resultado obtenido, es decir, matplotlib 2.0.2, que hasta el momento es su última versión.

 24 
Figura 1.59 Resultados de la búsqueda matplotlib
A continuación se muestra una ventana como la de la figura 1.60, en la cual se observa en qué
plataformas puede instalarse matplotlib. Se debe seleccionar la liga matplotlib-2.0.2-cp36-cp36m-
win32.whl.

Figura 1.60 matplotlib para diferentes plataformas


Entonces una vez que se descargó dicho archivo quedará en un archivo de distribución como
el mostrado en la figura 1.61. El cual también está en formato wheel.

Figura 1.61 Archivo de distribución de matplotlib


sympy es una biblioteca escrita en Python cuyo objetivo es reunir todas las características de un
sistema de álgebra computacional (CAS), ser fácilmente extensible y mantener el código todo lo
simple que sea posible. No requiere ninguna biblioteca externa, salvo para soporte gráfico. En su
funcionalidad se puede distinguir: manejo de enteros de precisión arbitraria y de números
racionales; simplificación básica, expansión, sustitución básica; manejo de funciones sobre el
cuerpo de los complejos; derivación, expansión en series de Taylor; límites, integración,
divisibilidad y factorización de polinomios; resolución de ecuaciones algebraicas, diferenciales y

 25 
sistemas; operaciones con matrices simbólicas, etc. Para descargarlo nuevamente en la página de
PyPI, en la opción search escribir sympy (figura 1.62) y hacer clic.

Figura 1.62 Buscando sympy en la página de PyPI


Enseguida se mostrará una ventana (figura 1.63) en la cual se verán los resultados obtenidos en
la búsqueda de sympy. Se muestran varios resultados, pero hay que hacer clic en el primer resultado
obtenido, es decir, sympy 1.1, que hasta el momento es su última versión.
En la ventana de la figura 1.64 se muestra un único resultado para descargar sympy, por lo que
solamente hace falta dar clic sobre la liga o sobre el botón de Download sympy-1.1.tar.gz.

Figura 1.63 Resultados de la búsqueda sympy Figura 1.64 Único resultado a descargar
Una vez que se descargó dicho archivo quedará en un archivo doblemente compacta, esto es
primero en .tar y luego en .gz (figura 1.65).

Figura 1.65 Archivo de distribución de sympy

 26 
1.4.2 Instalando numpy, matplotlib y sympy
Normalmente, un paquete se puede descargar manualmente desde el repositorio, tal como se
acaba de hacer, y después instalarlo con el propio Python pero lo habitual es utilizar la herramienta
pip que permite desde la consola instalar, desinstalar, actualizar, listar, buscar y realizar otras
operaciones relacionadas con los proyectos publicados (en PyPI o en otros repositorios basados en
la misma tecnología).
Cuando pip instala un paquete hará lo propio con sus dependencias, es decir, con aquellos
paquetes de los que depende su funcionamiento. En la actualidad pip es la herramienta para
gestionar paquetes aconsejada por la PyPA (Python Packaging Authority), la principal autoridad
en recomendaciones sobre empaquetado y distribución de aplicaciones Python.
A continuación, se hará un recorrido por los conceptos esenciales para introducirse en este
mundo de los paquetes de distribución Python y, también, se explicará el uso de pip.
Lo primero que se debe hacer es escribir en buscar o ejecutar en el inicio de Windows cmd, para
ejecutar el símbolo del sistema (figura 1.66), pero además hay que hacerlo como administrador
(figura 1.67).
La ventana, que generalmente es llamada símbolo del sistema o línea de comandos, es una
aplicación basada en texto para ver, manejar y manipular archivos en la computadora pero sin el
entorno gráfico. Otros nombres para el símbolo del sistema son: consola o terminal.

Figura 1.66 Ejecutando cmd Figura 1.67 Ejecutando cmd como administrador
Ya que se está ejecutando el símbolo del sistema (figura 1.68), se trabajará exclusivamente en
modo de texto.

 27 
Figura 1.68 Trabajando en símbolo del sistema en línea de comandos
Ahora bien para instalar un paquete en Python hay básicamente dos maneas de hacerlo,
dependiendo si se tienen o no conexión a internet al momento de instalarlo.
1. Sin conexión a internet.
a. pip install --use-wheel paquete.whl
b. python setup.py install
2. Con conexión a internet.
a. pip install paquete
Estás maneras de instalar un paquete se explicarán a continuación mediante un ejemplo de cada
caso. Primeramente, se verá cómo instalar un paquete sin conexión a internet al momento de
instalarlo. Para hacer dicha instalación se deberá cambiar al directorio en el cual se encuentre el
paquete a instalar (figura 1.69), recordar que para cambiarse de directorio, en línea de comandos,
es con la instrucción cd.

Figura 1.69 Carpeta con los paquetes a instalar


Algo importante que se tiene que hacer es verificar que Python se encuentre en el path de sistema
(figura 1.70), esto se hace escribiendo simplemente path y dar <enter>. Si no se muestra que Python

 28 
se encuentra en el path del sistema fue porque no se seleccionó la opción Add Python 3.6 to path
al momento de instalarlo (figura 1.71).
Se puede reinstalar Python seleccionado dicha opción.

Figura 1.70 Python en la path del sistema Figura 1.71 Opción no


seleccionada
Como ya se tiene el paquete a instalar, no hay necesidad de contar en estos momentos con una
conexión a internet para que se pueda instalar el mismo. La sintaxis para instalar un paquete wheel
es:
pip install --use-wheel paquete.whl
El primer paquete a instalar es el matplotlib, el cual efectivamente es un paquete wheel, por lo
que para instalarlo basta con escribir
pip install --use-wheel matplotlib-2.0.2-cp36-cp36m-win32.whl
y presionar <enter>.
Con esto quedará rápidamente instalado matplotlib.

Figura 1.72 Instalando matplotlib como un paquete wheel

 29 
Como se observó, se utiliza la herramienta pip. Normalmente, en una instalación Python 3.4 o
posterior la herramienta pip está lista para su uso. En determinadas circunstancias (porque se haya
excluido previamente de la instalación, se haya desinstalado en un momento dado o se trate de un
entorno virtual) es posible que no esté disponible.
Ahora para instalar numpy basta con escribir:
pip install --use-wheel numpy-1.13.1-cp36-none-win32.whl
y presionar nuevamente <enter> (figura 1.73).

Figura 1.73 Instalando numpy


Falta instalar sympy, pero este no es un paquete wheel, por lo que será necesario descomprimirlo
para poder instalarlo. Un buen descompresor es el 7zip, el cual es libre y de código abierto. Se
puede descargar de la dirección www.7-zip.org (figura 1.74).

Figura 1.74 Página principal del descompresor 7zip


Una vez que se ha descargado he instalado el 7zip, se procederá a descomprimir el sympy, el
cual, como se mencionó, tiene doble formato de compresión, primero en .tar y luego en .gz.
Se debe seleccionar el archivo sympy-1.1.tar.gz (figura 1.75) y con el clic derecho seleccionar
7-zip y extraer aquí (figura 1.76). Esto es para la primera descompresión del archivo.
Todo esto se hace en el ambiente gráfico de Windows, no en su línea de comandos.

 30 
Figura 1.75 Seleccionado archivo a Figura 1.76 Primera descompresión
descomprimir
El 7-zip, procederá a descomprimir el archivo (figura 1.77) y después de unos segundos
terminará el proceso. Cuando se ha terminado la primera descompresión, se ha creado una nueva
carpeta que se llama dist, se le tiene que seleccionar y entrar a ella (figura 1.78).

Figura 1.77 Proceso de descompresión Figura 1.78 Preparando la segunda descompresión


Como se observa hay un solo archivo en dicha solamente hay un archivo sympy-1.1.tar (figura
1.79), el cual se debe volver a descomprimir, esto de la misma forma anteriormente realizada.

Figura 1.79 Archivo de la carpeta dist


Una vez que se volvió a descomprimir el archivo se crea una nueva carpeta denominada sympy-
1.1 (figura 1.80).

Figura 1.80 Carpeta dist después de la segunda descompresión


Ahora si se cambia a la carpeta sympy-1.1 (figura 1.81) hay un archivo setup.py, el cual es la
base para instalar, sin conexión a internet, el paquete sympy.

 31 
Figura 1.81 Carpeta sympy-1.1
Para continuar con la instalación de sympy es necesario regresar al símbolo del sistema y
cambiar a la carpeta sympy-1.1.

Figura 1.82 Carpeta sympy-1.1 en símbolo del sistema


Una vez que se esté en dicha carpeta la sintaxis para su instalación es:
python setup.py install
y de nueva cuenta se presiona <enter>.

Figura 1.83 Instalando sympy

 32 
Enseguida se iniciará con la instalación de dicho paquete, pero como el mismo no es uno wheel,
su instalación lleva más tiempo (figura 1.84).

Figura 1.84 Instalando sympy


Después de varios minutos de terminará la instalación de sympy (figura 1.85).

Figura 1.85 Finalización de la instalación de sympy


Falta mencionar cómo se instala un paquete si se tiene conexión a internet al momento de su
instalación. La sintaxis para hacerlo es:
pip install paquete_a_instalar
Por ejemplo, hay que tratar de volver a instalar el paquete numpy con esta sintaxis (figura 1.86).
Entonces se escribiría pip install numpy y se presionaría la tecla <enter>

 33 
Figura 1.86 Instalando un paquete cuando se cuenta con conexión a internet
Como se observa el mismo no se instala, porque ya se había hecho con anterioridad, solamente
se muestra el mensaje de que los requerimientos ya han sido satisfechos, de cualquier forma esta
es la manera de instalar cualquier otro paquete cuando se tiene conexión a internet, sin necesidad
de descargar previamente el paquete.
Finalmente para ver qué paquetes se tienen instalados en Python (figura 1.87), basta con escribir:
pip freeze

Figura 1.87 Paquetes instalados en Python

1.5 Modos de trabajar con Python en Windows

Una vez que se tiene instalado Python, el ambiente gráfico de programación y los paquetes
requeridos para programar, ya es posible iniciar con dicha labor.
Existen tres maneras diferentes de trabajar con Python:
1. Editor de Python
2. Línea de comandos de Python

 34 
3. Con una GUI o un IDE de terceros
Para trabajar de la primera forma es necesario localizar, en los programas instalados en
Windows, el intérprete de Python (figura 1.88). Posteriormente hacer clic en la opción IDLE
(Python 3.6 32-bit), con lo que se cargará el editor de Python (figura 1.89).
Como se observa, el mismo es un editor con un entorno gráfico poco amigable. En realidad no
había necesidad de haberlo instalado, pues se instaló PyCharm.

Figura 1.88 Localizando Python Figura 1.89 Editor de Python


Al momento de instalar Python, basta con quitar la selección td/tk and IDLE (figura 1.90) para
que no se instale dicho editor.
La segunda manera de trabajar con Python es directamente en su línea de comandos o modo
terminal (figura 1.91), esto es, de modo texto exclusivamente. La cual se ejecuta con la opción
Python 3.6 (32-bit) de la figura 1.88. Esta es la manera normal de trabajar con Python, pero si se
quisiera trabajar todo el tiempo de esta forma no se hubiera instalado PyCharm como GUI.

Figura 1.90 Opción para no instalar el editor de Python

 35 
Figura 1.91 Línea de comandos de Python
Estas dos maneras de trabajar con Python se conocen como modo interactivo, y en estas formas
es precisamente cuando los comandos son leídos en la línea de comandos o editor de Python. En
este modo se espera el siguiente comando con el prompt primario, usualmente tres signos mayor
que (>>>). Para las líneas de continuación espera con el prompt secundario (cuando se usa sangría
en el programa), por defecto son tres puntos (...). Antes de mostrar el prompt primario, el intérprete
muestra un mensaje de bienvenida reportando su número de versión y una nota de copyright, tal
como se observa en la figuras 1.89 y 1.91.
Aunque la misma es muy útil cuando se quiere hacer algún programa sencillo y de forma rápida
o usar a Python como una calculadora, pero no es recomendable cuando se tiene que realizar un
programa más complejo, sobre todo cuando el mismo es largo y contiene muchas líneas de código.
La tercera manera de trabajar con Python, es con una GUI o un IDE de terceros, como es el caso
de PyCharm (figura 1.92). Existen muchas interfaces gráficas o entornos de desarrollo para
programar en Python, que, de una manera genérica, en el sitio web de Python, se les denomina
editores de Python.
Sin embargo se eligió PyCharm, para trabajar en este manual, por las características que posee
y que fueron mencionadas anteriormente.

 36 
Figura 1.92 PyCharm como GUI para programar en Python
En la dirección https://wiki.python.org/moin/PythonEditors (figura 1.93), se pueden encontrar
las direcciones de una gran cantidad de editores para Python. Además de mencionar su nombre,
también se muestra las plataformas en que se puede ejecutar, el lenguaje en el que fue realizado, el
tipo de licencia que posee y algunas notas sobre el mismo.

Figura 1.93 Editores para Python

1.6 Actividad a realizar

Mostrar evidencias de la descarga, instalación y configuración tanto del entorno gráfico (Python
3.6.2 y el GUI PyCharm) como del entorno de programación (numpy, sympy y matplotlib). Esto a
través de capturas de pantallas, además de describir cada una de ellas. Realizar esta actividad en
MicroSoft Word® y entregarla en la fecha indicada por el profesor.

 37 
Unidad 2 Fundamentos de programación en Python
2.1 Consideraciones iniciales

En Python es necesario indentar el programa, tal como se menciona más adelante, pero antes de
continuar se verá por qué se utiliza la palabra sangrado en lugar de indentación.
Indentación es un anglicismo (de la palabra inglesa indentation) de uso común en informática;
no es un término reconocido por la Real Academia Española (consultado en la vigesimosegunda
edición). La Real Academia recomienda utilizar “sangrado”. Este término significa mover un
bloque de texto hacia la derecha insertando espacios o tabuladores, para así separarlo del margen
izquierdo y mejor distinguirlo del texto adyacente; en el ámbito de la imprenta, este concepto
siempre se ha denominado sangrado o sangría.
En los lenguajes de programación de computadoras, la indentación es un tipo de notación
secundaria utilizado para mejorar la legibilidad del código fuente por parte de los programadores,
teniendo en cuenta que los compiladores o intérpretes raramente consideran los espacios en blanco
entre las instrucciones de un programa. Sin embargo, en algunos lenguajes de programación como
Python, el sangrado se utiliza para delimitar la estructura del programa permitiendo establecer
bloques de código.
Son frecuentes discusiones entre programadores sobre cómo o dónde usar el sangrado, si es
mejor usar espacios en blanco o tabuladores, ya que cada programador tiene su propio estilo.
También en Python la longitud máxima de una línea se recomienda que máximo sea de 79
caracteres.
El punto y coma “;” se puede usar para separar varias instrucciones en una misma línea, pero no
se aconseja su uso, sobre todo por cuestiones de legibilidad. Por ejemplo:
Edad = 15; print(Edad)
El código Python se escribe en cada línea desde la primera posición, excepto cuando es necesario
dejar el código sangrado. El sangrado en Python es obligatorio, como se mencionó anteriormente,
se hace con espacios en blanco o saltos de tabulación y sirve para agrupar bloques de líneas de
código que tienen relación a distintos niveles. Se utiliza con estructuras de control (IF-ELSE,
WHILE, FOR), con funciones y clases. Además, permite que la lectura del código sea legible y
agradable.

 38 
El sangrado se puede hacer con espacios y tabulaciones pero ambos tipos no se pueden mezclar
en la misma línea.
Aunque es posible sangrar con un único espacio en blanco lo normal es utilizar un número de
espacios múltiplo de cuatro en cada nivel de sangrado (cuatro, ocho, doce espacios, etc.), o bien,
distinto número de saltos de tabulación. Con PyCharm se pueden insertar los cuatro espacios
directamente con el tabulador.
¿Cómo funciona el sangrado en PyCharm? Cuando se presiona <enter> si la línea actual tiene
sangrado o si termina con dos puntos “:” (como es el caso de las funciones) la siguiente y sucesivas
líneas comenzarán sangradas. Para desangrar presionar la tecla de borrado <←>.
La barra invertida "\" al final de línea se emplea para dividir una línea muy larga en dos o más
líneas.
Las expresiones entre paréntesis "()", llaves "{}" y corchetes "[]" separadas por comas "," se
pueden escribir ocupando varias líneas.
Además el símbolo # se utiliza para poner comentarios en cualquier parte del programa, toda la
línea es ignorada por Python al momento de ejecutarlo.
Ejemplos de sangrado, división de líneas y comentarios en Python se muestran en la figura 2.1.

Figura 2.1 Ejemplos de sangrado, división de líneas y comentarios en Python


En la figura 2.1 se observa que la primer línea tiene escrito
# -*- coding: UTF8 -*-

 39 
esto se debe a que Python necesita que se le indique la codificación de caracteres que se utilizarán.
Y se le indica en la primera línea del código.
Aunque por default, los archivos fuente de Python son tratados como codificados en UTF8. En
esa codificación, los caracteres de la mayoría de los lenguajes del mundo pueden ser usados
simultáneamente en literales, identificadores y comentarios, a pesar de que la biblioteca estándar
usa solamente caracteres ASCII para los identificadores, una convención que debería seguir
cualquier código que sea portable. Para mostrar estos caracteres correctamente, el editor debe
reconocer que el archivo está en UTF8 y usar una tipografía que soporte todos los caracteres del
archivo.
También es posible especificar una codificación distinta para los archivos fuente. Para hacer
esto, pone una o más líneas de comentarios especiales luego de la línea del # para definir la
codificación del archivo fuente:
# -*- coding: encoding -*-
Con esa declaración, todo en el archivo fuente será tratado utilizando la codificación encoding
en lugar de UTF8. La lista de posibles codificaciones se puede encontrar en la Referencia de la
Biblioteca de Python, en la sección sobre codecs.
Por ejemplo, si el editor utilizado no soporta la codificación UTF8 e insiste en usar alguna otra,
como Windows-1252, se puede escribir:
# -*- coding: cp1252 -*-
y usar todos los caracteres del conjunto de Windows-1252 en los archivos fuente. El comentario
especial de la codificación debe estar en la primera.
En Python existen 30 palabras reservadas (keywords), las cuales son:
and, as, assert, break, class, continue, def, del, elif,
else, except, finally, for, from, global, if, import, in, is,
lambda, nonlocal, not, or, pass, raise, return,
try, while, with, yield
Las mismas no se pueden utilizar al momento de declarar variables, objetos, funciones y clases.
Finalmente, Python es un lenguaje case sensitive, esto significa que diferencia entre mayúsculas
y minúsculas, por lo que, por ejemplo, las tres variables Valor, valor y VALOR serán consideradas
en Python como tres variables diferentes.

 40 
2.2 Números

En Python se pueden representar números enteros, reales y complejos. Estos tipos de números
de verán a continuación con más detalles.

2.2.1 Enteros
Los números enteros son aquellos que no tienen decimales, tanto positivos como negativos
(además del cero). En Python se pueden representar mediante el tipo int (de integer, entero) o el
tipo long (largo). La única diferencia es que el tipo long permite almacenar números más grandes.
Es aconsejable no utilizar el tipo long a menos que sea necesario, para no malgastar memoria.
El tipo int de Python se implementa a bajo nivel mediante un tipo long de C. Y dado que Python
utiliza C por debajo, como C, y a diferencia de Java, el rango de los valores que puede representar
depende de la plataforma.
En la mayoría de las computadoras, el long de C se almacena utilizando 32 bits, esto es, mediante
el uso de una variable de tipo int de Python se pueden almacenar números de –231 a 231– 1, o lo que
es lo mismo, de –2,147’483,648 a 2,147’483,647. En plataformas de 64 bits, el rango es de –
9’223,372’036,854’775,808 hasta 9’223,372’036,854’775,807.
El tipo long de Python permite almacenar números de cualquier precisión, limitado por la
memoria disponible en la computadora.
Al asignar un número a una variable esta pasará a tener tipo int, a menos que el número sea tan
grande como para requerir el uso del tipo long. En la versión 3 no es posible asignar un tipo long
directamente a un número, se tiene que convertir con la función long(). En versiones anteriores se
podía indicar que un número se almacenaba de tipo long añadiendo una L al final del número,
como sería el caso de 27L para representar un entero largo.
La literal que se asigna a la variable también se puede expresar como un octal, anteponiendo 0o,
como sería el caso de 0o27 para indicar un número en octal, que en base 10 sería el valor 23. En
versiones anteriores bastaba con anteponer 0. O bien en hexadecimal, anteponiendo 0x, como el
caso de 0x27, cuyo resultado en base 10 es 39.
En la figura 2.2 se tiene un programa donde se mostrarán los números de tipo entero, long, octal
y hexadecimal. Si se ejecuta el mismo, el resultado se observa en la figura 2.3.

 41 
Figura 2.2 Números enteros, entero largo, octal y Figura 2.3 Resultado de ejecutar el programa
hexadecimal
Como se observa en la figura 2.3, todos los resultados impresos muestran primeramente el valor
de la variable en base 10 y enseguida el tipo de dato. La función print() muestra el resultado en
pantalla, mientras que la función type() devuelve el tipo de dato de la variable que se quiere
imprimir. Además como se ve, todos estos números son tratados como enteros.
En el programa de la figura 2.2 se observa, que después de la declaración de la codificación en
Python, se tienen las líneas mostradas en la figura 2.4, las mismas se utilizan para importar los
paquetes que se descargaron e instalaron anteriormente. En algunas ocasiones no son necesarios
todos, pero como se van a utilizar constantemente, es recomendable declararlos.

Figura 2.4 Importando los paquetes instalados

2.2.2 Reales
Los números reales son los que tienen decimales. En Python se expresan mediante el tipo float.
En otros lenguajes de programación, como C, también se tiene el tipo double, similar a float pero
de mayor precisión (double = doble precisión).
Python, sin embargo, implementa su tipo float a bajo nivel mediante una variable de tipo double
de C, es decir, utilizando 64 bits, luego en Python siempre se utiliza doble precisión, y en concreto

 42 
se sigue el estándar IEEE 754: 1 bit para el signo, 11 para el exponente, y 52 para la mantisa. Esto
significa que los valores que se pueden representar van desde ±2.2250738585072020 x 10-308 hasta
±1.7976931348623157×10308.
La mayor parte de los lenguajes de programación siguen el mismo esquema para la
representación interna. Para representar un número real en Python se escribe primero la parte
entera, seguido de un punto y por último la parte decimal. También se puede utilizar notación
científica al añadir una e (de exponente) para indicar un exponente en base 10.
En la figura 2.5 se tiene un pequeño programa para mostrar números reales tanto en forma
decimal y como en notación científica, así como su tipo. En la figura 2.6 se observa el resultado al
ejecutarlo.

Figura 2.5 Números reales Figura 2.6 Resultado al ejecutar el programa

2.2.3 Complejos
La mayor parte de lenguajes de programación carecen de este tipo, aunque sea muy utilizado
por ingenieros y científicos en general.
En el caso de que se necesite utilizar números complejos, o simplemente se tenga curiosidad,
este tipo, llamado complex en Python, también se almacena usando coma flotante, debido a que
estos números son una extensión de los números reales. En concreto se almacena en una estructura
de C, compuesta por dos variables de tipo double, sirviendo una de ellas para almacenar la parte
real y la otra para la parte imaginaria.
Los números complejos en Python se representan de la siguiente forma:
complejo = parte_real + parte_imaginaria.j
En la figura 2.7 se tiene un programa para mostrar un número complejo, así como su tipo. En la
figura 2.8 se observa el resultado al ejecutarlo.

 43 
Figura 2.7 Números complejos Figura 2.8 Resultado al ejecutar el programa

2.3 Cadenas de caracteres

Además de números, Python puede manipular textos y cadenas de caracteres, las cuales pueden
ser expresadas de distintas formas. Pueden estar encerradas en comillas dobles ("...") o simples
('...') con el mismo resultado. La barra invertida (\) puede ser usada para mostrar caracteres
especiales, tal como se muestra en el programa de la figura 2.9. En la figura 2.10 se observa el
resultado al ejecutar dicho programa.
El carácter \’ es utilizado para poner una comilla en el lugar indicado dentro de la cadena de
caracteres y \” para poner comillas dobles. \t se utiliza para incluir los espacios en blanco de un
tabulador y \n para un salto de línea.

Figura 2.9 Cadenas de caracteres Figura 2.10 Resultado al ejecutar el programa


La salida de cadenas está encerrada en comillas y los caracteres especiales son escapados (salto
de línea y tabulador) con barras invertidas, tal como se mencionó. Aunque esto a veces luzca
diferente de la entrada (las comillas que encierran pueden cambiar), las dos cadenas son
equivalentes. La cadena se encierra en comillas dobles si la cadena contiene una comilla simple y

 44 
ninguna doble, de lo contrario es encerrada en comillas simples. La función print() produce una
salida más legible, omitiendo las comillas que la encierran e imprimiendo caracteres especiales y
de salto de línea.
Si no se quiere que los caracteres antepuestos por \ sean interpretados como caracteres
especiales, se pueden usar cadenas crudas (raw) agregando una r antes de la primera comilla o
comillas, tal como se muestra en el programa de la figura 2.11 y cuyo resultado se muestra en la
figura 2.12.

Figura 2.11 Utilizando cadenas crudas Figura 2.12 Resultado al ejecutar el programa
Las cadenas de caracteres que quieran ser mostradas de forma literal pueden contener múltiples
líneas. Una forma es usar triples comillas sencillas o dobles ("""...""") o ('''...'''). El fin de línea es
incluido automáticamente, pero es posible prevenir esto agregando una \ al final de la línea. En la
figura 2.13 se muestra un programa que utiliza cadenas de forma literal, mientras que en la figura
2.14 se observa el resultado al ejecutarlo.

Figura 2.13 Cadenas de caracteres en forma literal Figura 2.14 Resultado al ejecutar el programa
Las cadenas de caracteres pueden ser concatenadas (pegadas o unidas) con el operador + y
repetidas con *. Además dos o más cadenas literales (aquellas encerradas entre comillas) una al
lado de la otra son automáticamente concatenadas.
Esto se ejemplifica en la figura 2.15, que muestra un programa en el cual se repite 3 veces “un”
y se concatena con “algo”. Además de concatenas las cadenas “Py” y “thon". El resultado al
ejecutar el programa se observa en la figura 2.16.

 45 
Figura 2.15 Repitiendo y concatenando cadenas Figura 2.16 Resultado al ejecutar el programa
de caracteres
Esto solo funciona con dos literales, no con variables ni expresiones, tal como se muestra en el
programa de la figura 2.17 y su respectiva ejecución mostrada en la figura 2.18.

Figura 2.17 Repitiendo y concatenando cadenas de Figura 2.18 Resultado al ejecutar el


caracteres programa
Si se quieren concatenar variables o una variable con un literal, se utiliza +. Si te tiene un texto
largo, este se puede poner en varios renglones utilizando paréntesis y comillas. El programa de la
figura 2.19 lo muestra más claramente, así como su respectiva ejecución (figura 2.20).

Figura 2.19 Concatenando una variable y una cadena, además de varias cadenas largas

Figura 2.20 Resultado al ejecutar el programa

 46 
2.3.1 Índices en cadenas de caracteres
Las cadenas de caracteres se pueden indexar (subíndices), el primer carácter de la cadena tiene
el índice 0. En Python no hay un tipo de dato para los caracteres; un carácter es simplemente una
cadena de longitud uno. En programa de la figura 2.21 se muestra el uso de los subíndices como se
observa el resultado al ejecutarlo (figura 2.22)

Figura 2.21 Utilizando subíndices Figura 2.22 Resultado al ejecutar el


programa
Los índices pueden ser números negativos, para empezar a contar desde la derecha. Esto se
muestra en el programa de la figura 2.23 y su respectiva ejecución en la figura 2.24

Figura 2.23 Utilizando subíndices negativos Figura 2.24 Resultado al ejecutar el


programa
Nota: ya que -0 es lo mismo que 0, los índice negativos comienzan desde -1.
Además de los índices, los rangos también están soportadas. Mientras que los índices son usados
para obtener caracteres individuales, los rangos permiten obtener sub-cadenas. Además en los
rangos el primer carácter es siempre incluido y el último es siempre excluido.
En el programa de la figura 2.25 se tiene el uso de rangos, mientras que en la figura 2.26 se
observa la ejecución del mismo.

 47 
Figura 2.25 Utilizando rangos Figura 2.26 Resultado al ejecutar el
programa
Nota: como el primero es siempre incluido, y que el último es siempre excluido. Esto asegura que:
s[:i] + s[i:] siempre sea igual a s (1)
En la figura 2.27 se muestra un programa en el cual se comprueba (1), tal como se observa en
la ejecución del mismo (figura 2.28).

Figura 2.27 Utilizando rangos Figura 2.28 Resultado al ejecutar el


programa
Los índices de los rangos tienen valores por defecto útiles; el valor por defecto para el primer
índice es cero, el valor por defecto para el segundo índice es la longitud de la cadena a obtener el
rango.
Una forma de recordar cómo funcionan los rangos es pensar en los índices como puntos entre
caracteres, con el punto a la izquierda del primer carácter numerado en 0. Luego, el punto a la
derecha del último carácter de una cadena de n caracteres tiene índice n.
En la figura 2.29 se muestra otro programa en el cual se nuevamente se utilizan rangos, además
en la figura 2.30 se tiene el resultado de la ejecución del mismo.

 48 
Figura 2.29 Utilizando rangos Figura 2.30 Resultado al ejecutar el
programa
Para aclarar un poco más lo de los rangos véase la siguiente tabla 2.1.
Tabla 2.1 Valores de índices en la palabra Python
Palabra P y t h o n
Índice positivo 0 1 2 3 4 5
Índice negativo -6 -5 -4 -3 -2 -1

La primer fila de números da la posición de los índices 0,...,6 en la cadena; la segunda fila da
los correspondientes índices negativos. El rango de i a j consiste en todos los caracteres entre los
puntos etiquetados i y j, respectivamente. Para índices no negativos, la longitud del rango es la
diferencia de los índices, si ambos entran en los límites. Por ejemplo, la longitud de val[1:3] es 2.
Intentar usar un índice que es muy grande resultará en un error. Esto se muestra en el programa
de la figura 2.31. Al intentar imprimir un carácter con el índice 42 de una cadena de 6 caracteres
se muestra el error de la figura 2.32. Sin embargo, índices fuera de rango en los rangos son
manejados satisfactoriamente, como se observa al imprimir b y c (figura 3.33). Al imprimir c el
resultado es una cadena vacía.

Figura 2.31 Utilizando índices Figura 2.32 Error al utilizar un índice Figura 2.33
grandes fuera de rango fuera de rango Índices fuera de
rango en el rango

 49 
Las cadenas de Python no pueden ser modificadas, es decir, son inmutables. Por eso, asignar un
carácter a una posición indexada de la cadena resulta en un error. El programa de la figura 2.34
tiene esta condición por lo que al ejecutarlo (figura 2.35) se presenta un error de ejecución.

Figura 2.34 Error al asignar en una cadena Figura 2.35 Resultado al ejecutar el programa
Si se necesita una cadena diferente, se deberá crear una nueva. Esto se muestra en el programa
de la figura 2.36, cuyo resultado al ejecutarlo se presenta en la figura 2.37.

Figura 2.36 Creando nuevas cadenas Figura 2.37 Resultado al ejecutar el programa
Finalmente, la función incorporada len() devuelve la longitud de una cadena de caracteres. Su
uso se muestra en el programa de la figura 2.38. Así como la ejecución del mismo se presenta en
la figura 2.39.

Figura 2.38 Utilizando la función len() Figura 2.39 Resultado al ejecutar el programa

2.4 Listas

Python tiene varios tipos de datos compuestos, usados para agrupar otros valores. El más versátil
es la lista, la cual puede ser escrita como una lista de valores (ítems) separados por coma entre
corchetes. Las listas pueden contener ítems de diferentes tipos, pero usualmente los ítems son del

 50 
mismo tipo. Como las cadenas de caracteres (y todos los otros tipos secuencias integrados), las
listas pueden ser indexadas. El manejo de los índices es el mismo que en las cadenas de caracteres.
En el programa de la figura 2.40 se tiene que un ejemplo del manejo de los índices, mientras que
en la figura 2.41 se muestra el resultado al ejecutar el programa.

Figura 2.40 Índices en listas Figura 2.41 Resultado al ejecutar el


programa
También en las listas se pueden utilizar rangos. Todas las operaciones de rangos devuelven una
nueva lista conteniendo los elementos pedidos. En el programa de la figura 2.42 se tiene un ejemplo
de la utilización de rangos en la lista cuadrados. Además el resultado al ejecutarlo se observa en la
figura 2.43.

Figura 2.42 Rangos en listas Figura 2.43 Resultado al ejecutar el


programa
Las listas también soportan operaciones como concatenación utilizando el signo +. En la figura
2.44 se tiene un programa que concatena dos listas y su resultado se muestra en la figura 2.45.

 51 
Figura 2.44 Concatenando listas Figura 2.45 Resultado al ejecutar el programa
A diferencia de las cadenas de caracteres, que son inmutables, las listas son un tipo mutable, es
posible cambiar el valor de su contenido. En la figura 2.46 se tiene un programa que modifica un
ítem de una lista y su resultado se muestra en la figura 2.47.

Figura 2.46 Cambiando un ítem en una lista Figura 2.47 Resultado al ejecutar el programa
Además se pueden agregar nuevos ítems al final de la lista, usando el método append() (más
adelante se verán otros métodos). En la figura 2.48 se tiene un programa en el cual se agregan ítems
al final de una lista. El resultado al ejecutarlo se muestra en la figura 2.49.

Figura 2.48 Agregando elementos a una lista Figura 2.49 Resultado al ejecutar el programa
También es posible asignar valores a un rango, y esto incluso puede cambiar la longitud de la
lista o vaciarla totalmente. En la figura 2.50 se tiene un programa que modifica algunos ítems de

 52 
una lista, además de eliminar algunos elementos y eliminar todos los elementos de la misma. El
resultado al ejecutarlo se muestra en la figura 2.51.

Figura 2.50 Utilizando rangos Figura 2.51 Resultado al ejecutar el programa


La función predefinida len() también sirve para obtener el tamaño de una lista. En la figura 2.52
se tiene un programa que muestra el tamaño de una lista y el resultado de su ejecución se muestra
en la figura 2.53.

Figura 2.52 Utilizando la función len() en listas Figura 2.53 Resultado al ejecutar el programa
Es posible anidar listas (crear una lista que contengan otras listas). En la figura 2.54 se tiene un
programa que muestra una lista cuyos ítems son un par de listas. Además de hacer referencia a
algunos de sus elementos. El resultado de su ejecución se muestra en la figura 2.55.

Figura 2.54 Lista de listas Figura 2.55 Resultado al ejecutar el programa

 53 
2.4.1 Más operaciones con listas
A continuación se mencionarán más operaciones que se pueden realizar con las listas y los
métodos utilizados para ello.
• Añadir un nuevo elemento: append. El cual ya se había mencionado.
• Extender una lista o unir dos listas: extend.
• Añadir un nuevo elemento en un índice determinado de la lista: insert.
• Editar un elemento en un índice determinado de la lista: =. También ya mencionado.
• Borrar elementos de la lista identificados por su índice: del.
• Borrar elementos de la lista identificados por su valor: remove.
• Invertir el orden de los índices en la lista: reverse.
• Ordenar una lista: sort.
• Crear una nueva lista ordenada a partir de otra lista no ordenada: sorted.
El uso de todos estos métodos sobre listas es mostrado en el programa de la figura 2.56. El
resultado al ejecutarlo se presenta en la figura 2.57.

Figura 2.56 Más operaciones con listas

 54 
Figura 2.57 Resultado al ejecutar el programa

2.5 Expresiones y operadores

En programación, al igual que en Python, una expresión se define de la siguiente forma:


1. Un valor es una expresión: 1.25, ’Juan’.
2. Una constante o variable es una expresión: pi, e, x.
3. Una función es una expresión: cos(x), sqrt(x).
4. Una combinación de valores constantes, variables, funciones y operaciones cumpliendo
unas determinadas reglas de construcción es una expresión: cos(pi * x) + 1.25, 2 * pi, n =
’Juan’.
Las expresiones según el resultado que producen, se clasifican en:
Numéricas
Son las producen un resultado de tipo numérico. Se constituyen mediante los operadores
aritméticos: pi * sqrt(x)
Alfanuméricas
Son las producen un resultado de tipo cadena de caracteres. Se constituyen mediante operadores
relacionales o de concatenación: “Don” + “N”
Lógicas:
Son las que producen resultados True o False. Se constituyen mediante los operadores
relacionales y lógicos: A > 0 AND B <= 5
Las siguientes son expresiones válidas en Python cuyo significado es más o menos claro:
20+32 hour1 hour*60+minute minute/60 5**2 (5+9)*(157)
La mayoría de los enunciados que se escriben en Python contienen expresiones. Una expresión
puede separarse en operadores y operandos.

 55 
Los operadores son caracteres que hacen alguna operación, como por ejemplo + o también otras
palabras clave. Los operadores requieren datos para operar, y a estos datos se les llama operandos.
Para la construcción de expresiones se pueden utilizar de forma general los tipos de operadores
que a continuación se verán.

2.5.1 Operadores aritméticos


Los operadores aritméticos en Python son los más sencillos, se utilizan para realizar operaciones
aritméticas básicas, es decir adiciones, substracciones, multiplicaciones, divisiones, modulo y
exponenciales. Estos operan sobre valores de tipo entero o real.
Los operadores aritméticos se resumen en la tabla 2.2.
Tabla 2.2 Operadores aritméticos
Operador Nombre Explicación Ejemplos
Retorna la suma de dos
3+5=8
+ Adición números o la concatenación
'a' + 'b' = 'ab'
de dos cadenas de caracteres.
5.2 Retorna un número
Retorna un número negativo
– Substracción negativo
o la resta entre dos números.
50 – 24 = 26
Retorna la multiplicación de
dos números o una cadena de 2*3=6
* Multiplicación
caracteres repetida tantas 'la' * 3 = 'lalala'
veces.
3 ** 4 = 81
** Potencia Retorna x a la potencia y.
es decir, 3*3*3*3
Retorna el cociente al dividir
/ División 4 / 3 = 1.3333333333333333
x por y
Retorna la parte entera del
// División entera 4 // 3 = 1
cociente al dividir x por y
Retorna el residuo al dividir 8%3=2
% Modulo.
x por y 25.5 % 2.25 = 0.75

En la figura 2.58se muestra un pequeño programa en el cual se utilizan los ejemplos de la tabla
2.2. Mientras que en la figura 2.59 se tienen los resultados al ejecutar al ejecutarlo, verificando que
efectivamente coinciden los resultados.

 56 
Figura 2.58 Utilizando operadores aritméticos Figura 2.59 Resultado al ejecutar el programa

2.5.2 Operadores lógicos


Estos realizan operaciones con operandos de tipo lógico o booleano y tiene como resultado un
dato también del mismo tipo.
En Python cualquier variable u objeto puede considerarse como una variable booleana. En
general los elementos nulos o vacíos se consideran False y el resto se consideran True.
Para comprobar si un elemento se considera True o False, se puede convertir a su valor booleano
mediante la función bool(), como en la figura 2.60. En la figura 2.61 se muestra el resultado.

Figura 2.60 Utilizando la función bool() Figura 2.61 Resultado al ejecutar el programa

Los resultados de las operaciones lógicas vienen determinados por las tablas de verdad
correspondientes a cada uno de los operadores lógicos. La tabla 2.3 muestra la tabla de verdad de
los operadores lógicos not, and y or.

 57 
Tabla 2.3 Tablas de verdad de los Operador lógico
x y not x not y x and y x or y
False False True True False False
False True True False False True
True False False True False True
True True False False True True
siendo x e y expresiones lógicas.
Los operadores lógicos se muestran con ejemplos en la tabla 2.4.
Tabla 2.4 Operadores lógicos
Operador Nombre Explicación Ejemplos
El operador not es unario, y
x = True
not NOT Booleano proporciona el valor Trae si su
not x retorna False
operando es False y viceversa.
El operador and da como
x = False, y = True
AND resultado el valor True si y sólo
and x and y retorna False
Booleano si son verdaderos sus dos
operandos.
El operador or retorna True si
cualquiera de sus operandos es x = True, y = False
or OR Booleano
True, y False cuando ambos x or y retornara True
operandos son False.
En la figura 2.62 se tiene un programa que muestra los resultados al utilizar los operadores
booleanos. Mientras que en la figura 2.63 se tienen los resultados al ejecutar el programa.

Figura 2.62 Utilizando operadores booleanos Figura 2.63 Resultado al ejecutar el programa

 58 
2.5.3 Operadores relacionales
Son operadores binarios en los que los operandos son enteros, reales o de cadenas de caracteres.
Los operadores relacionales (o de comparación) siempre retornan True o False. Además en Python
las comparaciones pueden encadenarse arbitrariamente.
Si los dos operandos son números deben ser convertidos a un mismo tipo. De otra forma,
siempre se retornara False. Todos los operadores relacionales dan lugar a resultados de tipo
booleano.
Los operadores relacionales se muestran en la tabla 2.3.
Tabla 2.5 Operadores relacionales
Operador Nombre Explicación Ejemplos
5 < 3 retorna False
< Menor que Compara si x es menor que y.
3 < 5 < 7 retorna True
> Mayor que Compara si x es mayor que y. 5 > 3 retorna True
Menor o igual Compara de si x es menor o x = 3, y = 6
<=
que igual que y. x <= y retorna True
Mayor o igual Compara de si x es mayor o x = 4, y = 3
>=
que igual que y. x >= y retorna True
x = 2, y = 2
Compara si dos números o
x == y retorna True
== Igual a cadenas de caracteres son
x = 'str', y = 'stR'
iguales.
x == y retorna False
Compara si dos números o
x = 2, y = 3
!= Diferente a cadenas de caracteres son
x!= y retorna True
diferentes.
En la figura 2.64 se tiene un programa en el que se utilizan operadores relacionales, mientras
que en la figura 2.65 se muestra el resultado al ejecutarlo.

Figura 2.64 Utilizando operadores relacionales Figura 2.65 Resultado al ejecutar el programa

 59 
Como se mencionó en anteriormente Python permite anidar varias comparaciones y el resultado
será verdadero si y sólo si todas las comparaciones lo son.
En programa de la figura 2.66 muestra comparaciones anidadas, mientras que en la figura 2.67,
se presenta el resultado el ejecutarlo.

Figura 2.66 Anidando comparaciones Figura 2.67 Resultado al ejecutar el programa


Anidar comparaciones no está permitido en otros lenguajes como PHP, en los que las
comparaciones deben combinarse mediante operadores lógicos and, lo que también puede hacerse
en Python.
En la figura 2.68 se tiene un pequeño programa en el cual se hace uso de operadores lógicos
para anidar comparaciones, mientras que en la figura 2.69 se tiene el resultado al ejecutar el
programa.

Figura 2.68 Anidando comparaciones con Figura 2.69 Resultado al ejecutar el programa
operadores lógicos

2.5.4 Operadores de asignación


Es muy común hacer operaciones matemáticas con una variable y luego asignar el resultado de
la operación en esta misma. En Python se utilizan diversos operadores de asignación para este tipo
de operaciones de asignación.
Los operadores de asignación son =, +=, =, *=, /=, **=, //=. En la tabla 2.6 se muestran dichos
operadores con ejemplos.

 60 
Tabla 2.6 Operadores de asignación
Operador Nombre Explicación Ejemplos
Es el más simple de todos y
asigna a la variable del lado
= Igual a izquierdo cualquier a=5
variable o resultado del
lado derecho.
Suma a la variable del lado a= 5
+= Suma-igual izquierdo el valor del lado a += 10 = 15, ya que equivale a
derecho. a = a + 10
Resta a la variable del lado a= 5
= Resta-igual izquierdo el valor del lado a = 10 = 5, ya que equivale a
derecho. a = a  10
Multiplica a la variable del a= 5
*= Producto-igual lado izquierdo el valor del a *= 10 = 50, ya que equivale a
lado derecho. a = a * 10
Divide a la variable del a = 15
/= División-igual lado izquierdo el valor del a /= 10 = 1.5, ya que equivale a
lado derecho. a = a / 10
Divide de forma entera la a = 15
División
//= variable del lado izquierdo a //= 10 = 1, ya que equivale a
entera-igual
el valor del lado derecho. a = a // 10
Divide de forma entera la a= 3
**= Potencia-igual variable del lado izquierdo a **= 4 = 81, ya que equivale a
el valor del lado derecho. a = a ** 4
Es importante señalar que en matemáticas el signo igual se utiliza tanto en las asignaciones
como en las comparaciones, mientras que en Python (y en otros muchos lenguajes de
programación) un signo igual (=) significa asignación, es decir, almacenar un valor en una variable
mientras que dos signos iguales seguidos (==) significa comparación, es decir, decir si es verdad o
mentira que dos expresiones son iguales.
Cuando se aprende a programar es habitual confundir una cosa con la otra (el error más frecuente
es escribir una sola igualdad en las comparaciones), por lo que se recomienda prestar atención a
este detalle.
En la figura 2.70 se tiene un programa que muestra el uso de los operadores de asignación,
mientras que en la figura 2.71 se tiene el resultado al ejecutarlo.

 61 
Figura 2.70 Utilizando operadores de asignación Figura 2.71 Resultado al ejecutar el programa
En Python se puede asignar un mismo valor a un conjunto de variables al mismo tiempo:
a=b=c=1
que equivale a asignar de forma individual a = 1, b = 1, c = 1.
La asignación múltiple también se puede hacer a varias variables del mismo o de diferentes tipos
al mismo tiempo:
a, b, c, d = 3, ‘hola’, True, 7
que equivale a asignar de forma individual a = 3, b = ‘hola’, c = True, d = 7.
En la figura 2.72 se muestra un programa donde se utiliza lo descrito de las asignaciones
múltiples, mientras que en la figura 2.73 se tiene la ejecución del mismo.

Figura 2.72 Asignaciones múltiples Figura 2.73 Resultado al ejecutar el programa

 62 
Además la asignación múltiple se puede utilizar para intercambiar los valores de 2 variables.
Tal como se observa en el programa de la figura 2.74 y su resultado en la figura 2.75.

Figura 2.74 Intercambiando valores mediante Figura 2.75 Resultado al ejecutar el programa
asignación múltiple

2.5.5 Operador paréntesis y expresiones anidadas


Es un operador que se utiliza para anidar expresiones o para agrupar subexpresiones y se muestra
en la tabla 2.7.
Tabla 2.7 Operador paréntesis.
Operador Nombre Ejemplo de expresión Resultado de expresión
() Paréntesis ((3+2)**215) / 2*5 25.0
(2**3) + (5 − 3) 10

Una expresión es interpretada de acuerdo a las normas particulares de precedencia (orden de


evaluación) y asociación para un lenguaje de programación en particular, en el caso de Python
dicho orden de evaluación se verá en el siguiente tema.
Como en matemáticas, la expresión es su valor evaluado, es decir, la expresión es una
representación de ese valor.
En la figura 2.76 se tiene un ejemplo de un programa de la utilización del operador paréntesis
para anidar expresiones, mientras que en la figura 2.77 se muestra la ejecución del mismo.

Figura 2.76 Utilizando el operador paréntesis Figura 2.77 Resultado al ejecutar el programa

 63 
2.5.6 Orden de evaluación
Si se tiene una expresión como 2 + 3 * 4, ¿Se hace primero la adición o la multiplicación?
Nuestras matemáticas de secundaria nos dicen que la multiplicación se debería hacer primero. Esto
significa que el operador de multiplicación tiene una precedencia más alta que operador de adición.
La tabla 2.8 es una tabla de precedencia para Python, empezando por la precedencia más baja
(menos obligatoria) hasta la más alta (más obligatoria). Entonces en una expresión dada, Python
evaluará primero los operadores y expresiones que más abajo estén en la tabla por sobre los que
están más arriba en esta.
La tabla 2.8 es mostrada por su completitud y fue tomada de Python Manual de Referencia. Es
mucho mejor agrupar operadores y operandos usando paréntesis para así especificar su precedencia
y hacer que el programa sea mucho más fácil de entender.
Tabla 2.8 Precedencia de los operadores en Python (de menor a mayor precedencia)

Operador Descripción
lambda Expresión Lambda
or OR Booleano
and AND Booleano
not x NOT Booleano
<, <=, >, >=,!=, == Comparaciones
+, – Adición y sustracción
*, /, //, % Multiplicación, División, División entera y modulo
+x, x Positivo, Negativo
** Potenciación
() Paréntesis

Existen operadores que aún no han sido vistos, pero se hará en capítulos posteriores.
En la tabla 2.8 los operadores con la misma precedencia son mostrados en la misma fila. Por
ejemplo + y  tienen la misma precedencia. Cuando se tienen operadores de la misma precedencia
Python evalúan izquierda a derecha, a excepción de los exponentes, ya que si una expresión
contiene muchas operaciones de exponentes, los operadores son aplicados de derecha a izquierda.
Si en una expresión se tienen varias subexpresiones anidadas con paréntesis, Python evalúa
primeramente los más internos y luego los externos tal como se vio en la figura 2.74.

 64 
A manera de ejemplo se evaluarán las siguientes expresiones:
a) ((3 + 2)**2  15) / 2 * 5
(5**2  15) / 2 * 5
(25  15) / 2 * 5
10 / 2 * 5
5*5
25

b) 5  2 > 4 and not 0.5 == 1/2


5  2 > 4 and not 0.5 == 0.5
3 > 4 and not 0.5 == 0.5
False and not 0.5 == 0.5
False and not True
False and False
False
Los resultados obtenidos al evaluar las expresiones anteriores se muestran en el programa de la
figura 2.78 y su resultado en la figura 2.79

Figura 2.78 Evaluando expresiones Figura 2.79 Resultado al ejecutar el programa

2.5.7 Cambiando el orden de evaluación


Para hacer que las expresiones sean más fáciles de leer podemos usar paréntesis. Por ejemplo,
2 + (3 * 4) es más fácil de entender que 2 + 3 * 4, el cual requiere el conocimiento de la precedencia
de los operadores. Además como con todo, el uso de los paréntesis debe ser razonable (no exagerar)
y no ser redundante como sería el caso de (2 + ((3 + 4) + 2)).
Hay una ventaja adicional de usar paréntesis – estos ayudan a cambiar el orden de evaluación.
Por ejemplo, si en una expresión quiere que la suma sea evaluada antes que la multiplicación puede
escribir algo como (2 + 3) * 4.
Los operadores son usualmente asociados de izquierda a derecha es decir si hay operadores con
la misma precedencia se evalúan empezando izquierda y terminando derecha. Por ejemplo, 2 + 3

 65 
+ 4 es evaluado como (2 + 3) + 4. Algunos operadores como el de asignación tienen asociatividad
de derecha a izquierda es decir a = b = c es tratado como a = (b = c).
Además tenemos que saber la asociatividad que presentan estos operadores, el not no tiene
asociatividad por ser unario, el and y or son asociativos por la izquierda ya que son binarios.

2.6 Estructura de control de flujo

Una estructura de control, es un bloque de código que permite agrupar instrucciones de manera
controlada. En este capítulo, se hablara sobre dos estructuras de control:
 Estructuras de control condicionales (IF)
 Estructuras de control iterativas (WHILE y FOR)

2.6.1 Estructura de control condicional IF


La estructura de control if permite que un programa ejecute unas instrucciones cuando se
cumplan una condición. En inglés if significa "si" (condición). La sintaxis en Python es la
siguiente:
if (expresión lógica):
instrucción v1
instrucción v2

instrucción vn
La primera línea contiene la condición a evaluar y es una expresión lógica. Esta línea debe
terminar siempre por dos puntos (:).
A continuación viene el conjunto de instrucciones (instrucción v1, instrucción v2,…, instrucción
vn) que se ejecutan cuando la condición se cumple (es decir, cuando la condición es verdadera). Es
importante señalar que este bloque debe ir sangrado, puesto que Python utiliza el sangrado para
reconocer las líneas que forman un bloque de instrucciones. El sangrado que se suele utilizar en
Python es de cuatro espacios, pero se pueden utilizar más o menos espacios. Al escribir dos puntos
(:) al final de una línea, PyCharm sangrará automáticamente las líneas siguientes. Para terminar un
bloque, basta con volver al principio de la línea.
En la figura 2.80 se muestra un programa que pide un número positivos al usuario y almacena
la respuesta en la variable "numero". Después comprueba si el número es negativo. Si lo es, el
programa avisa que no era eso lo que se había pedido. Finalmente, el programa imprime siempre

 66 
el valor introducido por el usuario. En la figura 2.81 se pueden ver dos ejecuciones de ese programa,
en la primera el usuario escribe un valor negativo y en la segunda un valor positivo:

Figura 2.80 Utilizando if Figura 2.81 Resultados al ejecutar el


programa en dos ocasiones
En la línea de la impresión se observa que hay una “f” antes del print. En Python 3.6 se ha
añadido una nueva notación para cadenas llamada cadenas "f", que simplifica la inserción de
variables y expresiones en las cadenas. Una cadena "f" contiene variables y expresiones entre llaves
({}) que se sustituyen directamente por su valor. Las cadenas "f" se reconocen porque comienzan
por una letra f antes de las comillas de apertura. Tal como se observa en el programa de la figura
2.82 y su ejecución en la figura 2.83.

Figura 2.82 Utilizando cadenas f Figura 2.83 Resultado al ejecutar el


programa

2.6.2.1 Dos alternativas en la estructura de control condicional IF... ELSE...


La estructura de control condicional if... else... permite que un programa ejecute unas
instrucciones cuando se cumple una condición y otras instrucciones cuando no se cumple esa
condición.
En inglés if significa "si" (condición) y else significa "si no". La sintaxis en Python es la
siguiente:
if (expresión lógica):
instrucción v1
instrucción v2

instrucción vn
 67 
else:
instrucción f1
instrucción f2

instrucción fn
La primera línea contiene la condición a evaluar. Esta línea debe terminar siempre por dos
puntos (:).
A continuación viene el conjunto de instrucciones (instrucción v1, instrucción v2,…, instrucción
vn) que se ejecutan cuando la condición se cumple (es decir, cuando la condición es verdadera).
Es importante señalar que este bloque debe ir sangrado, puesto que Python utiliza el sangrado para
reconocer las líneas que forman un bloque de instrucciones. El sangrado que se suele utilizar en
Python es de cuatro espacios, pero se pueden utilizar más o menos espacios. Al escribir dos puntos
(:) al final de una línea, PyCharm sangrará automáticamente las líneas siguientes. Para terminar un
bloque, basta con volver al principio de la línea.
Después viene la línea con la orden else, que indica a Python que el conjunto de instrucciones
(instrucción f1, instrucción f2,…, instrucción fn) que viene a continuación se tiene que ejecutar
cuando la condición no se cumpla (es decir, cuando sea falsa). Esta línea también debe terminar
siempre por dos puntos (:). La línea con la orden else no debe incluir nada más que el else y los
dos puntos.
En último lugar está el bloque de instrucciones sangrado que corresponde al else.
El programa de la figura 2.84 pregunta la edad al usuario y almacena la respuesta en la variable
edad. Después comprueba si la edad es inferior a 18 años. Si esta comparación es cierta, el
programa escribe que es menor de edad y si es falsa escribe que es mayor de edad. Finalmente el
programa siempre se despide, ya que la última instrucción está fuera de cualquier bloque y por
tanto se ejecuta siempre. En la figura 2.85 se pueden ver dos ejecuciones de dicho programa.

Figura 2.84 Utilizando if … else … Figura 2.85 Resultados al ejecutar el programa


en dos ocasiones

 68 
Aunque no es aconsejable, en vez de un bloque if... else... se podría escribir un programa con
dos bloques if, tal como se muestra en la figura 2.86. EL resultado de su ejecución sería el mismo
que el de la figura 2.85.

Figura 2.86 Utilizando dos bloques if en lugar de if… else…


Es mejor no hacerlo así por dos motivos:
 al poner dos bloques if estamos obligando a Python a evaluar siempre las dos condiciones,
mientras que en un bloque if... else... sólo se evalúa una condición. En un programa sencillo
la diferencia no es apreciable, pero en programas que ejecutan muchas comparaciones, el
impacto puede ser apreciable.
 utilizando else nos ahorramos escribir una condición (además, escribiendo la condición es
posible equivocarse, pero escribiendo else no).
Si por algún motivo no se quisiera ejecutar alguno de los conjuntos de instrucciones en los
bloques, el mismo debe contener al menos la instrucción pass (esta orden le dice a Python que no
tiene que hacer nada).
En el programa de la figura 2.87 se muestra el uso de la instrucción pass. Mientras que en la
figura 2.88 se tiene la ejecución del mismo.

Figura 2.87 Utilizando la instrucción pass Figura 2.88 Resultado al ejecutar el programa
Evidentemente este programa podría simplificarse cambiando la desigualdad (figura 2.89). Era
sólo un ejemplo para mostrar cómo se utiliza la orden pass. En la figura 2.90 se muestra la
ejecución de dicho programa.

 69 
Figura 2.89 Cambiando la desigualdad Figura 2.90 Resultado al ejecutar el programa

2.6.2.2 Sangrado de los bloques


Un bloque puede contener una o varias instrucciones. Todas las instrucciones del bloque deben
tener el mismo sangrado, tal como se observa en el programa de la figura 2.91. En la figura 2.92,
se tiene dos ejecuciones de dicho programa.

Figura 2.91 Mismo sangrado en if … else … Figura 2.92 Resultados al ejecutar el


programa en dos ocasiones
Se aconseja utilizar siempre el mismo número de espacios en el sangrado, aunque Python
permite que cada bloque tenga un número distinto, por lo que el programa de la figura 2.93 es
correcto, tal como lo muestran dos de sus ejecuciones (figura 2.94).

Figura 2.93 Diferentes sangrado en if … else … Figura 2.94 Resultados al ejecutar el


programa en dos ocasiones

 70 
Lo que no se permite es que en un mismo bloque haya instrucciones con distintos sangrados. En
la figura 2.95 se muestra un programa con diferentes sangrados en el mismo bloque. Mientras que
en la figura 2.96 se observa el error que se produce al ejecutarlo.

Figura 2.95 Diferentes sangrado en el mismo bloque Figura 2.96 Error de sangrado
En el este caso, la primera instrucción determina el sangrado de ese bloque, por lo que al
encontrar la segunda instrucción, con un sangrado mayor, se produce el error "unexpected indent"
(sangrado inesperado).
Dependiendo del orden de los sangrados, el mensaje de error al intentar ejecutar el programa
será diferente:
En la figura 2.97, la primera instrucción determina el sangrado de ese bloque, por lo que al
encontrar la segunda instrucción, con un sangrado menor, Python entiende que esa instrucción
pertenece a otro bloque, pero como no hay ningún bloque con ese nivel de sangrado, se produce el
error "unindent does not match any outer indentation level" (el sangrado no coincide con el de
ningún nivel superior), tal como se observa en la figura 2.98.

Figura 2.97 Diferentes sangrado en el mismo Figura 2.98 Error de sangrado


bloque
En la figura 2.99 se tiene que la segunda instrucción no tiene sangrado, por lo que Python
entiende que la bifurcación if ha terminado, y al encontrar un else sin su if correspondiente se
produce el error "invalid syntax" (sintaxis no válida), como se muestra en la figura 2.100.

 71 
Figura 2.99 Diferentes sangrado en el mismo bloque Figura 2.100 Error de sintaxis

2.6.2.3 Estructuras de control condicionales anidadas


Una estructura de control condicional puede contener a su vez otra estructura de control
condicional anidada, es decir, una estructura de control condicional dentro de otra estructura de
control condicional. Se pueden anidar tantas estructuras de control condicionales como se desee.
El programa de la figura 2.101 "adivina" el número pensado por el usuario, siendo un ejemplo
de estructuras de control condicionales anidadas. En la figura 2.102 se tiene un posible resultado
en la ejecución del mismo.
Además también se deben respetar las reglas sobre sangrado mencionadas anteriormente.

Figura 2.101 Estructuras de control condicionales anidadas Figura 2.102 Un posible resultado al
ejecutar el programa

 72 
2.6.2.4 Más de dos alternativas: IF... ELIF... ELSE...
La estructura de control if... elif... else... permite encadenar varias condiciones. elif es una
contracción de else if. La instrucción en Python tiene la siguiente sintaxis:
if condición 1:
instrucción 11

instrucción 1n
elif condición 2:
instrucción 21

instrucción 2n
else:
instrucción 31

instrucción 3n
Si se cumple la condición 1, se ejecuta el conjunto de instrucciones (instrucción 11,…,
instrucción 1n).
Si no se cumple la condición 1 pero sí que se cumple la condición 2, se ejecuta el conjunto de
instrucciones (instrucción 21,…, instrucción 2n).
Si no se cumplen ni la condición 1 ni la condición 2, se ejecuta el conjunto de instrucciones
(instrucción 31,…, instrucción 3n).
Esta estructura es equivalente a la siguiente estructura de if... else...
if condición 1:
instrucción 11

instrucción 1n
else:
if condición 2:
instrucción 21

instrucción 2n
else:
instrucción 31

instrucción 3n
Se pueden escribir tantos bloques elif como sean necesarios. El bloque else (que es opcional) se
ejecuta si no se cumple ninguna de las condiciones anteriores.

 73 
En las estructuras if... elif... else... el orden en que se escriben los casos es importante y, a
menudo, se pueden simplificar las condiciones ordenando adecuadamente los casos.
En estas estructuras se pueden distinguir dos tipos de situaciones:
a) Cuando los casos son mutuamente excluyentes
b) Cuando unos casos incluyen otros

2.6.2.5 Casos mutuamente excluyentes


Si se considera un programa que pide la edad y en función del valor recibido da un mensaje
diferente. Se pueden distinguir, tres situaciones:
 si el valor es negativo, se trata de un error
 si el valor está entre 0 y 17, se trata de un menor de edad
 si el valor es superior o igual a 18, se trata de un menor de edad
Los casos son mutuamente excluyentes, ya que un valor sólo puede estar en uno de los casos.
Un posible programa es el mostrado en la figura 2.103. En la figura 2.104 se pueden ver los tres
posibles resultado al ejecutar dicho programa.

Figura 2.103 Utilizando if … elif … else … Figura 2.104 Resultados posibles al


ejecutar el programa
El programa de la figura 2.103 funciona correctamente, pero los casos están desordenados. Es
mejor escribirlos en orden, para asegurarnos de no olvidar ninguna de las posibles situaciones. Se
podrían escribir de menor a mayor edad, aunque eso obliga a escribir otras condiciones (figura
2.105). En dicho programa se pueden simplificar las comparaciones (figura 2.106).

 74 
Figura 2.105 Ordenando los casos Figura 2.106 Simplificando las comparaciones
El programa de la figura 2.105 también funciona correctamente porque, en una estructura if...
elif... else…, cuando se cumple una de las comparaciones Python ya no considera las siguientes
condiciones, se cumplan o no. Por ejemplo, en la segunda comparación no hace falta comprobar
que la edad sea mayor que 0 porque si hubiera sido menor que 0 hubiera cumplido la primera
comparación y no estaría evaluando la segunda comparación, así que si está evaluando la segunda
comparación es que no se cumple la primera, es decir, que la edad es mayor que 0.
Pero hay que tener cuidado, porque si los casos del programa de la figura 2.107 se ordenan al
revés manteniendo las condiciones, el programa no funcionaría como se espera, puesto que al
escribir un valor negativo mostraría el mensaje "Es usted menor de edad" (figura 2.108).

Figura 2.107 Este programa no funciona correctamente Figura 2.108 Resultado incorrecto al
ejecutar el programa

2.6.2.6 Casos que incluyen otros


Considérese un programa que pide un valor y nos dice si el mismo es:
 múltiplo de dos,
 múltiplo de cuatro (y de dos)
 no es múltiplo de dos
Nota: El valor 0 se considerará múltiplo de 4 y de 2.

 75 
Los casos no son mutuamente excluyentes, puesto que los múltiplos de cuatro son también
múltiplos de dos. Por lo que el programa de la figura 2.109 no sería correcto, tal como lo muestra
un resultado de su ejecución (figura 2.110).

Figura 2.109 Este programa no funciona correctamente Figura 2.110 Resultado incorrecto al
ejecutar el programa
El error de este programa es que el número que cumple la segunda condición, cumple también
la primera. Si se escribe un múltiplo de cuatro, como también es múltiplo de dos, cumple la primera
condición y el programa ejecuta el primer bloque de instrucciones, sin llegar a comprobar el resto
de condiciones.
Una manera de corregir ese error es añadir en la primera condición (la de if) que el número no
sea múltiplo de cuatro (figura 2.111), su ejecución se muestra en la figura 2.112).

Figura 2.111 Corrigiendo el programa Figura 2.112 Resultado al ejecutar el


programa
También se podría haber escrito como el programa de la figura 2.113, su ejecución se muestra
en la figura 2.114.

 76 
Figura 2.113 Otra versión del programa Figura 2.114 Resultado al ejecutar el
programa
Este programa funciona porque los múltiplos de cuatro también son múltiplos de dos y el
programa sólo evalúa la segunda condición (la de elif) si no se ha cumplido la primera.
Pero todavía podemos simplificar más el programa, ordenando de otra manera los casos, tal
como se observa en el programa de la figura 2.115. Una ejecución del mismo se muestra en la
figura 2.116.
Este programa funciona correctamente ya que aunque la segunda condición (la de elif) no
distingue entre múltiplos de dos y de cuatro, si se escribe un múltiplo de cuatro, el programa no
llega a evaluar la segunda condición porque se cumple la primera (la de if).

Figura 2.115 Una nueva versión del programa Figura 2.116 Resultado al ejecutar el
programa
En general, el orden que permite simplificar más las expresiones suele ser considerar primero
los casos particulares y después los casos generales.
Si las condiciones if... elif... cubren todas las posibilidades, se puede no escribir el bloque else,
tal como se muestra en la figura 2.117.
A menudo el último bloque elif... se sustituye por un bloque else (figura 2.118).

 77 
Figura 2.117 Omitiendo else Figura 2.118 Sustituyendo elif por else

2.6.2 Estructura de control iterativa WHILE


Una estructura de control iterativa o ciclo, especifica una serie de condiciones que determinarán
si se ejecuta un conjunto de instrucciones una y otra vez. Cada vez que se cumplen las condiciones
adecuadas, se ejecuta una iteración en el ciclo. En Python hay dos tipos de ciclos while y for. Se
iniciará viendo el ciclo while.
while es una palabra que, en inglés, significa “mientras”, permite repetir la ejecución de un
conjunto de instrucciones mientras se cumpla una condición (es decir, mientras la condición tenga
el valor True).
El conjunto de instrucciones que se ejecuta dentro del ciclo puede ser cualquier cosa:
condiciones, otros ciclos, o cualquier otro tipo de instrucciones.
La sintaxis del ciclo while es la siguiente:
while condicion:
instrucción v1

instrucción vn
else:
instrucción f1

instrucción fn
Con esto en mente, véase el programa de la figura 2.119, para entender lo que hace. Por si no se
logra entender, su ejecución se muestra en la figura 2.120.

 78 
Figura 2.119 Utilizando while Figura 2.120 Resultado al ejecutar el
programa
En este programa mientras el valor de la variable numero valga menos que 3, el programa
imprimirá este hecho e incrementará su valor en una unidad. Por lo tanto, deberían verse 3
impresiones por la pantalla: la correspondiente a cuando numero vale 0 (primera iteración), cuando
vale 1 (segunda iteración) y cuando vale 2 (tercera iteración).
Cuando numero vale 3 la condición no se cumple, y por lo tanto se abandona el ciclo a través
de un else. En los ciclos de Python, una palabra else permite especificar qué se ejecuta cuando la
condición del ciclo deja de cumplirse. Al igual que en las condiciones if… elif… else, la parte else
es opcional.
Los ciclos pueden contener cualquier tipo de instrucciones en su interior, incluyendo, por
supuesto, condiciones como las que se han visto. Para explicar esto y además introducir dos
palabras especiales de Python relacionadas con el control de los ciclos, véase el programa de las
figura 2.121 y su ejecución en la figura 2.122.

Figura 2.121 Condiciones dentro de while Figura 2.122 Resultado al ejecutar el programa
Hay que ver porque el ciclo sólo se ejecuta 13 veces y por qué nunca se escribe la frase “Esto
nunca se ejecuta”, ni “Se sale del ciclo…”.

 79 
En el contexto de un ciclo, break significa romper el ciclo, y su efecto es dejar de ejecutarlo,
para no ejecutar más iteraciones aunque se cumpla la condición de continuidad. Tampoco se va a
ejecutar el bloque else, para mayor confusión. En este mismo contexto, continue significa
continuar con la siguiente iteración del ciclo, y su efecto es dejar de ejecutar el bloque del conjunto
de instrucciones de la iteración actual, para pasar a evaluar la condición de continuidad y, si se
debe hacer, ejecutar la siguiente iteración. Muchos autores están en contra del uso de continue y
break, porque en programas grandes hace que el mismo sea más difícil de entender, y que cueste
más trabajo evolucionarlo o corregir algún error.
En el programa de la figura 2.123 se ha modificado y se ha omitido el uso de break y continue,
haciéndolo más fácil de entender. Su ejecución se muestra en la figura 2.124.

Figura 2.123 Omitiendo break y continue Figura 2.124 Resultado al


ejecutar el programa
Otro ejemplo del uso de la estructura de control iterativa while es el programa de la figura 2.125
se encarga de imprimir la frase "Informes del Año”, mientras que año sea menor o igual a 2012.
Su ejecución se muestra en la figura 2.126.

Figura 2.125 Otro ejemplo del uso de while Figura 2.126 Resultado al ejecutar el programa
Si se observa la última línea: anio += 1, se podrá notar que en cada iteración, se incrementa el
valor de la variable que condiciona el ciclo (anio). Si no se hiciera, esta variable siempre sería igual

 80 
a 2001 y el ciclo se ejecutaría de forma infinita, ya que la condición (anio <= 2012) siempre se
estaría cumpliendo.

2.6.2.1 Ciclos infinitos


Si la condición del ciclo se cumple siempre, el ciclo no terminará nunca de ejecutarse y se tendrá
lo que se denomina un ciclo infinito. Aunque a veces es necesario utilizar ciclo infinitos en un
programa, normalmente se deben a errores que se deben corregir.
Los ciclos infinitos no intencionados deben evitarse pues significan perder el control del
programa. Para interrumpir un ciclo infinito, generalmente hay que pulsar la combinación de teclas
<ctrl>+<c>. Al interrumpir un programa se mostrará un mensaje de error como el de la figura
2.127.

Figura 2.127 Mensaje al interrumpir la ejecución de un ciclo infinito


En algunos el caso de PyCharm, en ocasiones no funciona esa combinación de teclas, por lo que
será necesario hacer clic en alguno de los botones en forma de cuadrados rojos, para interrumpir la
ejecución del programa. Se pueden localizar ya sea en la parte superior derecha de PyCharm o en
la barra inferior izquierda en la ventana de run (figura 2.128). Algo curioso es que se observa una
calavera en la barra inferior izquierda cuando se está interrumpiendo la ejecución del programa
(figura 2.129).

Figura 2.128 Botones rojos para interrumpir la Figura 2.129 Calavera mostrada al interrumpir la
ejecución del programa ejecución del programa
Por desgracia, es fácil programar involuntariamente un ciclo infinito, por lo que es inevitable
hacerlo de vez en cuando, sobre todo cuando se está aprendiendo a programar.
Estos algunos ejemplos de ciclo infinitos:

 81 
En la figura 2.130 el programador ha olvidado modificar la variable de control dentro del ciclo
y el programa imprimirá números 1 indefinidamente.
En la figura 2.131 el programador ha escrito una condición que se cumplirá siempre y el
programa imprimirá números consecutivos indefinidamente.
Se aconseja expresar las condiciones como desigualdades en vez de comparar valores. En la
figura 2.132 el programador ha escrito una condición que se cumplirá siempre y el programa
imprimirá números impares consecutivos indefinidamente.

Figura 2.130 Ciclo infinito 1 Figura 2.131 Ciclo infinito 2 Figura 2.132 Ciclo infinito 3

2.6.3 Estructura de control iterativa FOR


El ciclo for es algo más sofisticado que el while. Mientras que el ciclo while está pensado de
forma genérica, para aplicarlo a cualquier propósito, el ciclo for está pensado para recorrer listas,
cadenas, rangos, etc. En general cualquier elemento iterable.
La sintaxis de un ciclo for es la siguiente:
for variable in elemento iterable (lista, cadena, range, etc.):
instrucción v1

instrucción vn
No es necesario definir la variable de control antes del ciclo, aunque se puede utilizar como
variable de control una variable ya definida en el programa.
El cuerpo del ciclo ejecuta el conjunto de instrucciones (instrucción v1,…, instrucción vn) tantas
veces como elementos tenga el elemento iterable (elementos de una lista o de un range(), caracteres
de una cadena, etc.). En la figura 2.133 se muestra un programa que utiliza el ciclo for. Su ejecución
se observa en la figura 1.134.

 82 
Figura 2.133 Utilizando for Figura 2.134 Resultado al ejecutar el programa
Si no se quiere que Python añada un salto de línea al final de un print(), se debe añadir al final
el argumento end ="", como se observa en el segundo print() del programa de la figura 2.133.
En el programa anterior, los valores que toma la variable no son importantes, lo que importa es
que la lista tiene tres elementos y por tanto el ciclo se ejecuta tres veces. El programa de la figura
2.135 produciría el mismo resultado que el de la figura 2.133, tal como se observa en la figura
2.136.

Figura 2.135 Utilizando for Figura 2.136 Resultado al ejecutar el programa


Si la lista está vacía, el ciclo no se ejecuta ninguna vez. En la figura 2.137 se tiene un programa
que no ejecuta el ciclo for debido a que el elemento iterable está vacío. Su ejecución se muestra en
la figura 2.138.

Figura 2.137 for que no se ejecuta Figura 2.138 Resultado al ejecutar el programa
En los ejemplos anteriores, la variable de control i no se utilizaba en el bloque de instrucciones,
pero en muchos casos sí es utilizada. Cuando se utiliza, hay que tener en cuenta que la variable de

 83 
control va tomando los valores del elemento iterable. En la figura 2.139 se utiliza la variable de
control i y su ejecución se muestra en la figura 2.140.

Figura 2.139 Utilizando la variable de control Figura 2.140 Resultado al ejecutar el


programa
La lista puede contener cualquier tipo de elementos, no sólo números. El ciclo se repetirá
siempre tantas veces como elementos tenga la lista y la variable irá tomando los valores de uno en
uno. En el programa de la figura 2.141 se repite la cantidad de elementos de la lista. Su ejecución
se observa en la figura 2.142.

Figura 2.141 Utilizando la cantidad de elementos Figura 2.142 Resultado al ejecutar el programa
de la lista
La costumbre más extendida es utilizar la letra i como nombre de la variable de control, pero se
puede utilizar cualquier otro nombre válido. En la figura 2.143 se tiene un programa que no utiliza
la variable i como como variable de control. En la figura 2.144 se muestra su ejecución.

Figura 2.143 Utilizando otra variable de control Figura 2.144 Resultado al ejecutar el
programa
La variable de control puede ser una variable empleada antes del ciclo. El valor que tuviera la
variable no afecta a la ejecución del ciclo, pero cuando termina el ciclo, la variable de control

 84 
conserva el último valor asignado, tal como en el programa de la figura 2.145. Su ejecución se
observa en la figura 2.146.

Figura 2.145 Valor de la variable i Figura 2.146 Resultado al ejecutar el


programa
En vez de una lista se puede escribir una cadena, en cuyo caso la variable de control va tomando
como valor cada uno de los caracteres tal como se muestra en el programa de la figura 2.147,
mientras que su resultado se observa en la figura 2.148.

Figura 2.147 Cadena como variable de control Figura 2.148 Resultado al ejecutar el programa
En los ejemplos anteriores se ha utilizado una lista para facilitar la comprensión del
funcionamiento de los ciclos pero, si es posible hacerlo, se recomienda utilizar tipos range(), entre
otros motivos porque durante la ejecución del programa ocupan menos memoria en la
computadora.
El programa de la figura 2.149 contiene un ciclo for que se ejecuta 3 veces utilizando range, y
su ejecución se observa en la figura 2.150.

Figura 2.149 Utilizando range() Figura 2.150 Resultado al ejecutar el programa

 85 
También el número de iteraciones se puede hacer que dependa del desarrollo del programa. En
el programa de la figura 2.151 es el usuario quien decide cuántas veces se ejecuta el ciclo. La
ejecución del mismo se tiene en la figura 2.152.

Figura 2.151 Decidiendo las veces que se ejecuta el ciclo Figura 2.152 Resultado al ejecutar el
programa

2.6.3.1 Ciclos FOR anidados


Se habla de ciclos anidados cuando un ciclo se encuentra en el ciclo de instrucciones de otro
bloque. Al ciclo que se encuentra dentro del otro se le puede denominar ciclo interior. El otro ciclo
sería el ciclo exterior.
Los ciclos pueden tener cualquier nivel de anidamiento (un ciclo dentro de otro ciclo dentro de
un tercero, etc.).
Aunque en Python no es necesario, se recomienda que los nombres de las variables de control
de los ciclos anidados no coincidan, para evitar ambigüedades.

2.6.3.2 Ciclos anidados (variables independientes)


Se dice que las variables de los ciclos son independientes cuando los valores que toma la variable
de control del ciclo interno no dependen del valor de la variable de control del ciclo externo. En la
figura 2.153 se muestra un programa con ciclos for anidados y su ejecución en la figura 2.154.

Figura 2.153 Ciclos for anidados Figura 2.154 Resultado al ejecutar el programa

 86 
En general, el número de veces que se ejecuta el bloque de instrucciones del ciclo interno es el
producto de las veces que se ejecuta cada ciclo. Por eso en el programa de la figura 2.151 se ejecuta
6 veces.
En el programa de la figura 2.153 se han utilizado listas para facilitar la comprensión del
funcionamiento del ciclo pero, si es posible hacerlo, se recomienda utilizar tipos range(), entre
otros motivos porque durante la ejecución del programa ocupan menos memoria en la computadora
y se pueden hacer depender del desarrollo del programa. Esto se muestra en la figura 2.155 que es
equivalente 2.153 y su ejecución se observa en la figura 2.156.

Figura 2.155 Utilizando range() Figura 2.156 Resultado al ejecutar el programa

2.6.3.3 Ciclos anidados (variables dependientes)


Se dice que las variables de los ciclos son dependientes cuando los valores que toma la variable
de control del ciclo interno dependen del valor de la variable de control del ciclo externo. En el
programa de la figura 2.157 se utilizan variables dependientes. Su ejecución se presenta en la figura
2.158.

Figura 2.157 for con variables dependientes Figura 2.158 Resultado al ejecutar el programa
En el programa de la figura 2.157, el ciclo externo (el controlado por i) se ejecuta 3 veces y el
ciclo interno (el controlado por j) se ejecuta 1, 2 y 3 veces. Por ello la instrucción print() se ejecuta
en total 6 veces.
La variable i toma los valores de 1 a 3 y la variable j toma los valores de 0 a i, por lo que cada
vez el ciclo interno se ejecuta un número diferente de veces:
 Cuando i vale 1, range(i) devuelve la lista [0] y por tanto el ciclo interno se ejecuta una sola vez
y el programa escribe una sola línea en la que i vale 1 (y j vale 0).

 87 
 Cuando i vale 2, range(i) devuelve la lista [0, 1] y por tanto el ciclo interno se ejecuta dos veces
y el programa escribe dos líneas en la que i vale 2 (y j vale 0 o 1 en cada una de ellas).
 Cuando i vale 3, range(i) devuelve la lista [0, 1, 2] y por tanto el ciclo interno se ejecuta tres
veces y el programa escribe tres líneas en la que i vale 3 (y j vale 0, 1 o 2 en cada una de ellas).

2.7 Vectores y matrices


Existen diversos métodos para crear vectores y matrices en Python. Los más comunes son
utilizando la biblioteca estándar de Python, utilizando el paquete numpy (para trabajar de forma
numérica) y utilizando el paquete sympy (para trabajar de forma simbólica).
Los mismos serán descritos lo más detallado posible en los siguientes temas.

2.7.1 Usando la biblioteca estándar de Python


Las matrices y vectores no son estructuras propias de Python, pero se pueden crear matrices y
vectores con la biblioteca estándar de Python utilizando listas. Si se anidan listas se pueden
construir matrices de elementos, una simple lista sería el equivalente a un vector. Estas estructuras
de datos son muy útiles para operaciones matemáticas. Se debe tener en cuenta que problemas
matemáticos complejos son resueltos utilizando matrices. Además, también son prácticas para
almacenar ciertos datos, aunque no se traten estrictamente de representar matrices en el sentido
matemático.
En Python una matriz es una lista de listas que se puede interpretar desde el punto de vista
matemático. Es decir, la estructura m = [[1, 2], [3, 4]] se la interpreta como la matriz 2×2 cuya
primera fila es (1, 2) y cuya segunda fila es (3, 4), pero esto no deja de ser una interpretación.
Para representar una matriz, se debe crear una función específica, sino solamente se mostrará
como una lista de listas. En la figura 2.159 se muestra un programa que imprime una matriz y una
función realizada por el usuario que la formatea para su representación. El resultado de su ejecución
se observa en la figura 2.160.

 88 
Figura 2.159 Imprimiendo matrices Figura 2.160 Resultado al ejecutar el
programa
En la penúltima línea de la función se orbserva “:>3s”, esto significa es tamaño de la cadena es
3 y alineado a la derecha, lo cual es equivalente a utilizar el formato %3s.
En Python no se puede crear un vector vacío o una matriz vacía con "datos = []" y luego dar
valor a un elemento con "datos[0]=5", porque se obtendría un mensaje de error que avisa de que se
ha salido del rango de los datos. Se deben reservar todas las posiciones o bien usar el método
append(). En el programa de la figura 2.161, en la primer parte se reservan posiciones y luego se
le asignan valores a un vector, en la segunda parte se utiliza el método append() también para crear
un vector. El resultado de su ejecución se muestra en la figura 2.162.

Figura 2.161 Creando vectores Figura 2.162 Resultado al ejecutar


el programa
También se puede saber la cantidad de datos con la función len(), eliminar un elemento con el
método remove(), insertar en una cierta posición con el método insert(), o añadir toda una nueva

 89 
lista de datos con +. El uso de esta función y métodos muestran en el programa de la figura 2.161.
El resultado al ejecutarlo se muestra en la figura 2.164.

Figura 2.163 Modificando vectores Figura 2.164 Resultado al ejecutar el programa


Como una matriz es una lista de listas, para crearla, se utiliza el operador repetición *, que se
utiliza en las listas. Por ejemplo, para crear una matriz de 34 y asignarle valores se requiere con
un programa como el de la figura 2.165. El resultado de su ejecución se muestra en la figura 2.166.

Figura 2.165 Creando matrices Figura 2.166 Resultado al


ejecutar el programa
Para eliminar un elemento de una matriz, también se puede utilizar el método remove() que
elimina la primer lista que tenga una coincidencia. Así mismo para insertar una lista en una cierta
posición dentro de la matriz, se utiliza el método insert(). En una matriz hay que tener cuidado al
insertar elementos, ya que se pudiera dar el caso de que el resultado no sea una matriz como tal.
Esto se muestra en el programa de la figura 2.167, el resultado al ejecutarlo en la figura 2.168.

 90 
Figura 2.167 Modificando matrices Figura 2.168 Resultado al
ejecutar el programa

2.7.2 Utilizando el paquete numpy


Con las siguientes funciones de numpy se pueden crear una matriz o un vector en Python.
Cuando se conoce el tamaño pero no conocemos los datos que va a contener, o cuando por cualquier
motivo queremos matrices llenas de ceros o de unos. Para ello se utilizan las funciones empty(),
zeros() y ones(), que aceptan como argumento una lista con las dimensiones de la matriz o del
vector. En el programa de la figura 2.169 se muestra como crear matrices con numpy, mientras que
el resultado de la ejecución del mismo se muestra en la figura 2.170.

Figura 2.169 Creando matrices con numpy Figura 2.170 Resultado al ejecutar el programa
Hay que usar la función empty() con cuidado. Aunque es ligeramente más rápida que zeros(),
al rellenar todas las posiciones con valores aleatorios hay que asegurarse de que se va a sobrescribir
dichos valores, porque si no se obtendrían resultados desastrosos.
Para crear una matriz identidad, esto es, una matriz cuadrada con unos en la diagonal, se utiliza
usar la función identity(). Para un caso un poco más general, sin que sean matrices necesariamente

 91 
cuadradas, se puede usar eye(). El uso de estas funciones se muestra en el programa de la figura
2.171, mientras que el resultado de su ejecución se observa en la figura 2.172.

Figura 2.171 Matrices especiales con numpy Figura 2.172 Resultado al ejecutar el programa
Cuando se conoce todos los valores de la matriz o el vector antes de crearlo, se puede utilizar la
función array() y pasarle como argumento una lista o, en general, una secuencia. Esto se muestra
en el programa de la figura 2.173. El resultado de su ejecución del mismo se muestra en la figura
2.174.

Figura 2.173 Matrices especiales con numpy Figura 2.174 Resultado al ejecutar el programa
También es posible crear vectores como las funciones arange() y linspace().
arrange() devuelve valores uniformemente espaciados dentro de un intervalo dado, su sintaxis
es arange([inicio, ] fin, [pasos])
donde: inicio es el valor inicial del intervalo, es opcional y su default es cero; fin es valor final del
intervalo y pasos es el espaciado entre los valores, también es opcional y si se omite su
default es uno.
linspace() devuelve números uniformemente espaciados en un intervalo especificado con un
manejo cuidadoso de los puntos finales. Aunque es similar a arange() pero esta función usa un
tamaño de paso (en lugar del número de muestras). Su sintaxis es

 92 
linspace(inicio, fin, num=escalar, endpoint=True, retstep=False)
donde: inicio es el inicio de la secuencia; fin es el valor final de la secuencia; num es opcional y
representa el número de muestras a generar; endpoint es un valor booleano y es opcional,
si es True, fin es la última muestra. De lo contrario, no está incluido, su valor
predeterminado es True y retstep también es booleano y opcional, si es True, devuelve
(muestras, pasos), donde pasos es el espaciado entre muestras.
Ejemplos del uso de estas funciones se muestran en el programa de la figura 2.175. El resultado
de su ejecución se tiene en la figura 2.176.

Figura 2.175 Utilizando arange() y linspace() Figura 2.176 Resultado al ejecutar el


programa
También las funciones range() y arrange() son muy similares, pero range() devuelve un
"objeto de rango" especializado, mientras que arange() devuelve una matriz numpy. Por lo que si
se trabaja con este paquete se recomienda utilizar arange() que es más rápido.

2.7.2.1 Operaciones con matrices


Para los casos de la suma y resta, hay que tener en cuenta que solo se pueden sumar o restar
matrices que tengan las mismas dimensiones, es decir que si tengo una matriz A de dimensión 32
(3 filas y 2 columnas) solo se va a poder sumar o restar la matriz B si esta también tiene 3 filas y 2
columnas. Además cualquier matriz se puede multiplicar directamente por un escalar. El método
shape() muestra la dimensión de la matriz. Esto se muestra en el programa de la figura 2.177 y el
resultado de su ejecución se observa en la figura 2.178.

 93 
Figura 2.177 Operaciones con matrices Figura 2.178 Resultado al ejecutar el programa
La regla para la multiplicación de matrices es que el número de columnas de la primera matriz
debe ser igual al número de filas de la segunda matriz; y el resultado de esta multiplicación va a
tener el mismo número de filas que la primera matriz y el número de las columnas de la segunda
matriz. Es decir, que si se tiene una matriz A de dimensión 34 y se multiplica por una matriz B de
dimensión 42, el resultado va a ser una matriz C de dimensión 32. Para multiplicarlas se utiliza
el método dot(). Algo a tener en cuenta a la hora de multiplicar matrices es que la propiedad
conmutativa no se cumple. A  B no es lo mismo que B  A. Esto se muestra en el programa de la
figura 2.179, mientras que el resultado al ejecutarlo se tiene en la figura 2.180.

Figura 2.179 Multiplicando matrices Figura 2.180 Resultado al ejecutar el programa


En este último programa se ve que la propiedad conmutativa no se cumple, es más, Python arroja
un error, ya que el número de columnas de B no coincide con el número de filas de A, por lo que
ni siquiera se puede realizar la multiplicación de B  A.

 94 
Además de los arrays, con numpy también se pueden manejar matrices. Aunque parecen lo
mismo, se utilizan de manera un poco distinta, pero el resultado a final de cuentas es el mismo.
Entonces si se quiere utilizar matrices, entonces se usa la función matrix().
Otra operación común de matrices de su transpuesta. Para obtenerla se utiliza la función
transpose() o el método .T de la matriz, siendo sus salidas son idénticas. Esto se observa más
claramente en el programa de la figura 2.181. El resultado de su ejecución se tiene en la figura
2.182.

Figura 2.181 Transponiendo matrices Figura 2.182 Resultado al ejecutar el programa


Las ventajas de usar matrices en el fondo son muy pocas y además la mayoría de funciones de
numpy maneja arrays, así que se tendría que convertir entre ambos tipos constantemente. Además
como se ve en el programa de la figura 2.183 en su ejecución (figura 2.184) es el mismo que el del
programa de la figura 2.181. Por lo que básicamente es indistinto manejar arrays o matrices.

Figura 2.183 Transponiendo arreglos Figura 2.184 Resultado al ejecutar el programa

 95 
2.7.2.2 Otros métodos para arreglos en numpy
Existen otros métodos para arreglos, los cuales pueden ser muy útiles.
A.astype (T)
Crea una nueva matriz con los elementos de A, pero como tipo T.
A.copy()
Crea una nueva array como una copia exacta de A.
A.reshape(dims)
Devuelve una nueva matriz que es una copia de los valores A pero tiene la dimensión dada por
dims.
A.resize(dims)
Cambia la dimensión de la matriz A, pero lo hace en la misma matriz.
A.mean()
Devuelve la media de los valores en A.
A.var ()
Devuelve la varianza de los valores en A.
En el programa de la figura 2.185 se muestra es usos de todos estos métodos. El resultado al
ejecutarlo se tiene en la figura 2.186.

Figura 2.185 Métodos para matrices Figura 2.186 Resultado al ejecutar el programa

 96 
2.7.2.3 Expansión de arreglos
Si los objetos que se están operando no tienen las mismas dimensiones, numpy puede adaptar
algunas de ellas para completar la operación. Esto se denomina broadcasting en inglés.
numpy alinea los arrays a la derecha y empieza a comprobar las dimensiones por el final. Si son
todas compatibles realiza la operación, y si no lanza un error. Dos dimensiones son compatibles si
• Son iguales, o
• Una de ellas es 1.
Si los objetos no tienen el mismo número de dimensiones, se asume que las restantes son 1. Si
dos dimensiones son distintas pero compatibles, la menor se expande hasta tener el tamaño de la
mayor. Un ejemplo de expansión se muestra en el programa de la figura 2.187. El resultado al
ejecutarlo se tiene en la figura 2.188.

Figura 2.187 Expandiendo arreglos Figura 2.188 Resultado al ejecutar el programa

2.7.2.4 Leer o guardar datos de una matriz en un archivo


En el ámbito científico es frecuente almacenar y trasladar paquetes de datos en archivos escritos
en, por ejemplo, código ASCII. Python incorpora varias funciones que permiten la lectura y
escritura en estos archivos facilitando su manejo. Un ejemplo de ello es el la función loadtxt() que
permite abrir los datos contenidos en un archivo de texto con extensión .txt o .dat. Su sintaxis es:
loadtxt(fname, dtype=<type 'float'>, comments='#', delimiter=None, converters=None,
skiprows=0, usecols=None, unpack=False, ndmin=0)
donde:
fname: Nombre del archivo para leer.
dtype: tipo de datos, opcional, Tipo de datos de la matriz resultante; default: float.
comments: str o secuencia, opcional, caracteres utilizados para indicar el inicio de un comentario;
defecto: '#'.

 97 
delimiter: str, opcional, cadena utilizada para separar los valores. De forma predeterminada, se trata
de cualquier espacio en blanco.
converters: dict, opcional, un diccionario que asigna el número de columna a una función que
convertirá esa columna en un flotante.
skiprows: int, opcional, omite las primeras líneas de skiprows; valor predeterminado: 0.
usecols: int o secuencia, opcional, qué columnas leer, siendo 0 la primera.
unpack: bool, opcional, si es True, la matriz devuelta se transpone, de modo que los argumentos se
pueden desempaquetar utilizando x, y, z = loadtxt (...). El valor predeterminado es False.
ndmin: int, opcional, la matriz devuelta tendrá al menos dimensiones ndmin.
Por ejemplo, si se desean leer los datos contenidos en el archivo entrada.txt (figura 2.189) y
realzar algunas manipulaciones con los datos leídos.

Figura 2.189 Archivo de entrada


En el programa de la figura 2.190 se leen los datos del archivo, luego se redimensionan para
crear una matriz, enseguida se crea otra matriz también redimensionado los datos y finalmente se
obtiene la transpuesta de la matriz A. El resultado al ejecutarlo se muestra en la figura 2.191.

Figura 2.190 Leyendo y manipulando datos Figura 2.191 Resultado al ejecutar el


programa
El tipo de matriz (dtype=int) se añade para indicar que la matriz es de tipo entera, la forma
predeterminada para los datos es tipo real (dtype = float).
Otras funciones que también sirven para leer datos son:

 98 
• load() se utiliza para leer datos en el formato comprimido de numpy, que suele tener las
extensiones .npy o .npz.
• fromfile() sirve para leer datos en formato binario.
• genfromtxt() es más flexible que loadtxt(), y es crucial cuando el archivo está mal formateado
o faltan valores en los datos. En la mayoría de los casos es suficiente con usar loadtxt().
Ya que se ha visto cómo leer archivos con numpy, es lógico que también se pretenda guardar
los datos procesados en archivos de texto. La contrapartida de la función loadtxt() para escritura
es, la función savetxt(). Tiene dos argumentos obligatorios: el nombre del archivo y el array que
se guardará. Su comportamiento por defecto es guardar los datos con 18 cifras decimales, pero esto
se puede cambiar con el argumento fmt.
La sintaxis de savetext() es:
savetxt(fname, X, fmt='%.18e', delimiter=' ', newline='\n', header='', footer='', comments='# ')
donde:
fname: nombre de archivo o manejador de archivo
X: Datos a guardar en un archivo de texto.
fmt: str o secuencia de strs, opcional
delimiter: str, opcional, cadena o carácter que separa las columnas.
newline: str, opcional, líneas de separación de caracteres o caracteres.
header: str, opcional, cadena que se escribirá al principio del archivo.
footer: str, opcional, cadena que se escribirá al final del archivo.
comments: str, opcional, cadena que se añadirá a las cadenas de encabezado y pie de página, para
marcarlas como comentarios.
Si se quieren guardar los datos resultantes después de haberlos procesado del archivo de entrada
en el programa de la figura 2.190, se tiene que agregar una línea adicional al mismo. Por lo que el
programa quedaría como el mostrado en la figura 2.192.
El formato (%d) se añade para indicar que los datos en el archivo de salida deben ser enteros,
además que el delimitador para separar las columnas es la coma, al igual que la línea de separación
entre los caracteres.

 99 
Figura 2.192 Guardando datos resultantes
En la figura 2.193 se muestra el archivo de salida con el formado seleccionado.

Figura 2.193 Archivo de salida

2.7.3 Utilizando el paquete sympy


En el tema 4.5 Algebra Lineal, se verá detalladamente la utilización del paquete sympy para la
creación de vectores y matrices, así como las principales operaciones que se pueden realizar con
ellos.

2.8 Actividades a realizar

Codificar y ejecutar en Python los programas para los problemas indicados en cada caso, además
de seguir las indicaciones y/o restricciones, en caso de que las hubiera. En cada problema se
muestran una o varias figuras con posibles resultados al ejecutar el programa.

2.8.1 Programas que no utilizan estructuras de control


a) Solicitar dos números y calcular su media aritmética. En la figura 2.196 se muestra un posible
resultado al ejecutar el programa.

 100 
Figura 2.194 Posible resultado al ejecutar el programa
b) Solicitar el peso (en kilogramos) y la altura (en metros) de una persona y calcular su índice de
masa corporal (IMC). El IMC se calcula con la fórmula IMC = peso / altura2. En la figura 2.195
se muestra un posible resultado al ejecutar el programa.

Figura 2.195 Posible resultado al ejecutar el programa


c) Solicitar una distancia en pies y pulgadas y calcular dicha distancia en centímetros. En la figura
2.196 se muestra un posible resultado al ejecutar el programa.

Figura 2.196 Posible resultado al ejecutar el programa


d) Solicitar una temperatura en grados Celsius y convertirla a grados Fahrenheit. En la figura 2.195
se muestra un posible resultado al ejecutar el programa.

Figura 2.197 Posible resultado al ejecutar el programa


e) Solicitar una temperatura en grados Fahrenheit y convertirla a grados Celsius. En la figura 2.198
se muestra un posible resultado al ejecutar el programa.

Figura 2.198 Posible resultado al ejecutar el programa


f) Solicitar una cantidad de segundos y calcular cuántos minutos y segundos son. En la figura
2.199 se muestran dos posibles resultados al ejecutar el programa.

Figura 2.199 Dos posibles resultados al ejecutar el programa

 101 
g) Solicitar una cantidad de segundos y calcular cuántas horas, minutos y segundos son. En la
figura 2.200 se muestra un posible resultado al ejecutar el programa.

Figura 2.200 Posible resultado al ejecutar el programa


h) Solicitar una cantidad y calcular cuántas gruesas, docenas y unidades son. Se recuerda que una
gruesa son doce docenas. En la figura 2.201 se muestra un posible resultado al ejecutar el
programa.

Figura 2.201 Posible resultado al ejecutar el programa

2.8.2 Programas que utilizan estructuras de control condicionales, pero no iterativas


a) Solicitar dos números enteros y calcular su división, escribiendo si la división es exacta o no,
además de tener en cuenta que no se puede dividir por cero. En la figura 2.202 se muestran tres
posibles resultados al ejecutar el programa.

Figura 2.202 Tres posibles resultados al ejecutar el programa


b) Solicitar dos números y calcular cuál es el menor y cuál el mayor o si son iguales. En la figura
2.203 se muestran dos posibles resultados al ejecutar el programa.

Figura 2.203 Dos posibles resultados al ejecutar el programa


c) Solicitar el año actual y un año cualquiera y calcular cuántos años han pasado desde ese año o
cuántos años faltan para llegar a ese año. Cuando la diferencia sea 1 año, escribirlo en singular,
además indicar si son el mismo año. En la figura 2.204 se muestran cuatro posibles resultados
al ejecutar el programa.

 102 
Figura 2.204 Cuatro posibles resultados al ejecutar el programa
d) Solicitar dos números enteros y calcular si el mayor es múltiplo del menor. En la figura 2.005
se muestran cuatro posibles resultados al ejecutar el programa.

Figura 2.205 Cuatro posibles resultados al ejecutar el programa


e) Solicitar tres números y calcular si son los tres iguales, si hay dos iguales o si son los tres
distintos. En la figura 2.206 se muestran tres posibles resultados al ejecutar el programa.

Figura 2.206 Tres posibles resultados al ejecutar el programa


f) Solicitar un año y calcular si es bisiesto o no. Se recuerda que los años bisiestos son múltiplos
de 4, pero los múltiplos de 100 no lo son, aunque los múltiplos de 400 sí. En la figura 2.207 se
muestran cuatro posibles resultados al ejecutar el programa.

Figura 2.207 Cuatro posibles resultados al ejecutar el programa


g) Solicitar los coeficientes de una ecuación de primer grado (ax + b = 0) y calcular la solución. Se
recuerda que una ecuación de primer grado puede no tener solución, tener una solución única,
o que todos los números sean solución. La fórmula para calcular las soluciones es x = b / a. En
la figura 2.208 se muestran tres posibles resultados al ejecutar el programa.

 103 
Figura 2.208 Cuatro posibles resultados al ejecutar el programa
h) Solicitar los coeficientes de una ecuación de segundo grado (ax² + bx + c = 0) y calcular la
solución. Se recuerda que una ecuación de segundo grado puede no tener solución, tener una
solución única, tener dos soluciones o que todos los números sean solución. La fórmula general
𝑏 ± √𝑏 2 4𝑎𝑐
de las soluciones cuando hay dos soluciones es 𝑥 = . En la tabla 2.9 se muestran
2𝑎

algunos ejemplos de posibles respuestas de acuerdo a los valores de los coeficientes (el orden
de los ejemplos no tiene por qué corresponder con el orden de las condiciones). En la figura
2.209 se muestra un posible resultado al ejecutar el programa.

Tabla 2.9 Coeficientes y sus soluciones


a b c Solución
1 2 2 Sin solución real
2 7 3 Dos soluciones: x1=0.5 y x2=3.0
1 2 1 Una solución: x1 = x2 = 1.0
0 0 5 Sin solución
0 0 0 Todos los números son solución
0 3 2 Una solución: x1 = 0.666...
Figura 2.209 Posible resultado al ejecutar el
programa
i) Preguntar primero si se quiere calcular el área de un triángulo o la de un círculo. Si se contesta
que se quiere calcular el área de un triángulo, el programa tiene que pedir entonces la base y la
altura y escribir el área. Si se contesta que se quiere calcular el área de un círculo, el programa
tiene que pedir entonces el radio y escribir el área. En la figura 2.210 se muestran dos posibles
resultados al ejecutar el programa.

Figura 2.210 Dos posibles resultados al ejecutar el programa

 104 
j) Solicitar una distancia en centímetros y convertir esa distancia en kilómetros, metros y
centímetros (escribiendo solamente las unidades necesarias). En la tabla 2.10 se muestran
algunos ejemplos de cómo debe presentarse la conversión requerida. En la figura 2.211 se
muestran un posible resultado al ejecutar el programa.
Tabla 2.10 Ejemplos de conversión
Distancia en cm Conversión
100 1m
240005 2 km, 400 m, 5 cm
67 67 cm
300004 3 km, 4 cm
Figura 2.211 Posibles resultado al ejecutar el
programa
k) Solicitar el peso (en kilogramos) y la altura (en metros) de una persona y calcular su índice de
masa corporal (IMC). El IMC se calcula con la fórmula IMC = peso / altura2. Además de acuerdo
a la Organización Mundial de la Salud (OMS) indicar su clasificación (Tabla 2.11). En la figura
2.212 se muestran un posible resultado al ejecutar el programa.
Tabla 2.11 Clasificación del IMC según la OMS
IMC Clasificación
<16.00 Infrapeso: Delgadez Severa
16.00 - 16.99 Infrapeso: Delgadez moderada
17.00 - 18.49 Infrapeso: Delgadez aceptable
18.50 - 24.99 Peso Normal
25.00 - 29.99 Sobrepeso
30.00 - 34.99 Obeso: Tipo I
35.00 - 40.00 Obeso: Tipo II
>40.00 Obeso: Tipo III
Figura 2.212 Posibles resultado al
ejecutar el programa

2.8.3 Programas generales, utilizando todas las estructuras de control


a) Solicitar dos números enteros y encontrar los números pares e impares entre dichos números.
El segundo número debe ser mayor o igual que el primero. En la figura 2.213 se muestran tres
posibles resultados al ejecutar el programa.

 105 
Figura 2.213 Tres posibles resultados al ejecutar el programa
b) Solicitar un número entero mayor que cero y que calcular sus divisores. Tener en cuenta que los
divisores son siempre menores (o iguales) que la mitad del número. Es decir, no hace falta probar
todos los números entre 1 y el propio número, sino únicamente hasta la mitad. Si se hace así, no
hay que olvidarse de añadir el propio número a la lista de divisores. En la figura 2.214 se
muestran dos posibles resultados al ejecutar el programa.

Figura 2.214 Dos posibles resultados al ejecutar el programa


c) Solicitar cuántos números se van a introducir, pedir esos números, y mostrar un mensaje cada
vez que un número no sea mayor que el primero. En la figura 2.215 se muestran dos posibles
resultados al ejecutar el programa.

Figura 2.215 Dos posibles resultados al ejecutar el programa


d) Solicitar cuántos números se van a introducir, pedir esos números, y mostrar un mensaje cada
vez que un número no sea mayor que el anterior. En la figura 2.216 se muestran dos posibles
resultados al ejecutar el programa.

 106 
Figura 2.216 Dos posibles resultados al ejecutar el programa
e) Solicitar cuántos números se van a introducir, pedir esos números y escribir cuántos negativos
se han introducido. En la figura 2.217 se muestran tres posibles resultados al ejecutar el
programa.

Figura 2.217 Tres posibles resultados al ejecutar el programa


f) Solicitar cuántos números se van a introducir, pedir esos números, y mostrar al final cuántos
han sido pares y cuántos impares. En la figura 2.218 se muestran dos posibles resultados al
ejecutar el programa.

Figura 2.218 Dos posibles resultados al ejecutar el programa


g) Solicitar un número entero mayor que 1 y que escribir si el número es un número primo o no.
En la figura 2.219 se muestran cuatro posibles resultados al ejecutar el programa.

Figura 2.219 Cuatro posibles resultados al ejecutar el programa


h) Solicitar cuántos números se van a introducir, pedir esos números (que puedan ser decimales) y
calcular su suma. En la figura 2.220 se muestran dos posibles resultados al ejecutar el programa.

 107 
Figura 2.220 Dos posibles resultados al ejecutar el programa
i) Solicitar dos números enteros y calcular la suma de todos los enteros desde el primer número y
el segundo. Además escribir la suma realizada. En la figura 2.221 se muestran dos posibles
resultados al ejecutar el programa.

Figura 2.221 Dos posibles resultados al ejecutar el programa


j) Solicitar cuántos números se van a introducir, pedir esos números, y calcular el mayor, el menor
y la media aritmética. En la figura 2.222 se muestran dos posibles resultados al ejecutar el
programa.

Figura 2.222 Dos posibles resultados al ejecutar el programa


k) Solicitar un número entero mayor que cero y calcular su factorial. En la figura 2.223 se muestran
dos posibles resultados al ejecutar el programa.

Figura 2.223 Dos posibles resultados al ejecutar el programa


l) Solicitar un número entero mayor que 1 y calcular su descomposición en factores primos.
Mientas no se ingrese un número mayor que uno volver a preguntar. En la figura 2.224 se
muestran tres posibles resultados al ejecutar el programa.

 108 
Figura 2.224 Tres posibles resultados al ejecutar el programa
NOTA: En esta unidad no se codificarán ni ejecutarán programas que impliquen matrices ni
vectores. La utilización de estas estructuras se hará a manera de funciones, por lo que
serán incluidas en las actividades de la unidad 3.

 109 
Unidad 3 Programación de funciones
3.1 Definición de funciones

Una función es un fragmento de código con un nombre asociado que realiza una serie de tareas
y devuelve un valor. A los fragmentos de código que tienen un nombre asociado y no devuelven
valores se les suele llamar procedimientos. En Python no existen los procedimientos, ya que cuando
no se especifica un valor de retorno la función devuelve el valor None.
Además de ayudarnos a programar y depurar dividiendo el programa en partes las funciones
también permiten reutilizar código.
Las funciones se pueden crear en cualquier punto de un programa, escribiendo su definición. La
sintaxis en Python para escribir una función es la siguiente:
def nombre(argumento 1, argumento 2, …, argumento n):
instrucción 1

instrucción n
return
La primera línea de la definición de una función contiene: la palabra reservada def; el nombre
de la función, se recomienda escribir todos los caracteres en minúsculas separando las palabras por
guiones bajos y paréntesis (que pueden incluir o no argumentos), finalizando con dos puntos (:).
Las instrucciones que forman la función se escriben con sangría con respecto a la primera línea.
Se puede indicar el final de la función con la palabra reservada return, aunque no es obligatorio
más que en algunos casos, sobre todo cuando que quiera devolver más de un valor.
Para poder utilizar una función en un programa se tiene que haber definido antes. Por ello,
normalmente las definiciones de las funciones se suelen escribir al principio de los programas.
Una función, no es ejecutada hasta tanto no sea llamada o invocada. Para ello es necesario
escribir su nombre y en caso de que haya argumentos separados por comas en los paréntesis.
Cuando una función, haga un retorno de datos, éstos, pueden ser asignados a una variable, tal
como se verá más adelante.
A la definición de una función le deben anteceder dos líneas en blanco. Lo mismo ocurre si se
tienen varias funciones en el programa. Aunque puede ser ejecutada con una línea en blanco o
ninguna, PyCharm, en ocasiones, mostrará un mensaje de advertencia como el de la figura 3.1.

 110 
Figura 3.1 Mensaje de advertencia de PyCharm
El en la figura 3.2 se muestra un programa que contiene una función y el resultado de la
ejecución de ese programa se observa en la figura 3.3.

Figura 3.2 Función en Python Figura 3.3 Resultado al ejecutar el


programa
El la figura 3.4 se muestra un programa incorrecto ya que intenta utilizar una función antes de
haberla definido, su ejecución se observa en la figura 3.5.

Figura 3.4 Llamado incorrecto a una función Figura 3.5 Resultado al ejecutar el
programa

 111 
3.2 Nombres y tipos de variables

Como se ha comentado anteriormente, una de las principales ventajas de las funciones es que
permiten reutilizar el código. Pero copiar y pegar funciones de un programa a otro puede producir
lo que se llama un conflicto de nombres de variables. En efecto, si la función que se pega en un
programa utiliza alguna variable auxiliar para algún cálculo intermedio y resulta que el programa
ya utilizaba una variable con el mismo nombre que esa variable auxiliar, los cambios en la variable
que se hagan en la función podrían afectar al resto del programa de forma imprevista.

3.2.1 Conflictos de nombres de variables


Para resolver el problema de los conflictos de nombres, los lenguajes de programación limitan
lo que se llama el alcance o el ámbito de las variables. Es decir, que los lenguajes de programación
permiten que una variable exista únicamente en el interior de una función y no afecte a otras
variables de mismo nombre situadas fuera de esa función.
Como las funciones pueden contener a su vez funciones, se suele hablar de niveles: el nivel más
alto sería el programa principal, el siguiente nivel serían las funciones incluidas en el programa
principal y cada vez que hay una función incluida dentro de otra estaríamos bajando un nivel.
El problema es más complicado de lo que parece a primera vista, porque a menudo también
interesará que una función pueda modificar variables que estén definidas en otros puntos del
programa. Así que los lenguajes de programación tienen que establecer mecanismos para aislar las
variables y evitar los conflictos de nombres, pero al mismo tiempo deben permitir el acceso a las
variables en los casos que así lo quiera el programador.
Aunque cada lenguaje tiene sus particularidades, el mecanismo más habitual se basa en los
siguientes principios:
 cada variable pertenece a un ámbito determinado: al programa principal o a una función.
 las variables son completamente inaccesibles en los ámbitos superiores al ámbito al que
pertenecen
 las variables pueden ser accesibles o no en ámbitos inferiores al ámbito al que pertenecen (el
lenguaje puede permitir al programador elegir o no esa accesibilidad)
 en cada función, las variables que se utilizan pueden ser entonces:

 112 
• variables locales: las que pertenecen al ámbito de la función (y que pueden ser accesibles a
niveles inferiores)
• variables libres: las que pertenecen a ámbitos superiores pero son accesibles en la función

3.2.2 Conflictos de nombres de variables en Python


Python sigue estos principios generales, pero con algunas particularidades:
 En los lenguajes tipificados, como se debe declarar las variables que se utilizan, la declaración
se aprovecha para indicar si la variable pertenece a la función o procede de un ámbito superior.
Pero como Python no es un lenguaje tipificado, el ámbito de pertenencia de la variable debe
deducirse del programa siguiendo unas reglas que se detallan más adelante (aunque Python
también permite declarar explícitamente el ámbito en los casos en que se quiera un ámbito
distinto al determinado por las reglas).
 Python distingue tres tipos de variables: las variables locales y dos tipos de variables libres
(globales y no locales):
• variables locales: las que pertenecen al ámbito de la función (y que pueden ser accesibles a
niveles inferiores)
• variables globales: las que pertenecen al ámbito del programa principal.
• variables no locales: las que pertenecen a un ámbito superior al de la función, pero que no
son globales.
 Si el programa contiene solamente funciones que no contienen a su vez funciones, todas las
variables libres son variables globales. Pero si el programa contiene una función que a su vez
contiene una función, las variables libres de esas "subfunciones" pueden ser globales (si
pertenecen al programa principal) o no locales (si pertenecen a la función).
 Para identificar explícitamente las variables globales y no locales se utilizan las palabras
reservadas global y nonlocal. Las variables locales no necesitan identificación. La palabra
reservada nonlocal se introdujo en Python 3.
A continuación, se detallan las reglas y situaciones posibles, acompañadas de ejemplos.

 113 
3.2.3 Variables locales
Si no se han declarado como globales o no locales, las variables a las que se asigna valor en una
función se consideran variables locales, es decir, sólo existen en la propia función, incluso cuando
en el programa exista una variable con el mismo nombre, como muestra el programa de la figura
3.6. Su ejecución se observa en la figura 3.7.

Figura 3.6 Variable local Figura 3.7 Resultado al ejecutar el programa


Las variables locales sólo existen en la propia función y no son accesibles desde niveles
superiores, como puede verse en el programa de la figura 3.8. La ejecución del mismo se tiene en
la figura 3.9.

Figura 3.8 Variable local Figura 3.9 Resultado al ejecutar el programa


Si en el interior de una función se asigna valor a una variable que no se ha declarado como
global o no local, esa variable es local a todos los efectos. Por ello el programa de la figura 3.10 da
un error (figura 3.11).

 114 
Figura 3.10 Variables locales Figura 3.11 Resultado al ejecutar el programa

3.2.4 Variables libres globales o no locales


Si a una variable no se le asigna valor en una función, Python la considera libre y busca su valor
en los niveles superiores de esa función, empezando por el inmediatamente superior y continuando
hasta el programa principal.
Si a la variable se le asigna valor en algún nivel intermedio la variable se considera no local y
si se le asigna en el programa principal la variable se considera global, como muestran los
siguientes ejemplos.
En el programa de la figura 3.12, la variable libre a de la función se considera global porque
obtiene su valor del programa principal. Su ejecución se tiene en la figura 3.13.

Figura 3.12 Variable global Figura 3.13 Resultado al ejecutar el programa


En el programa de la figura 3.14, la variable libre a de la función sub_funcion() se considera no
local porque obtiene su valor de una función intermedia. Su ejecución se puede observar en la
figura 3.15.

 115 
Figura 3.14 Variable no local Figura 3.15 Resultado al ejecutar el programa
Si a una variable que Python considera libre (porque no se le asigna valor en la función) tampoco
se le asigna valor en niveles superiores, Python dará un mensaje de error, como muestra el
programa de la figura 3.16 en su ejecución (figura 3.17).

Figura 3.16 Variable libre no definida Figura 3.17 Resultado al ejecutar el programa

3.2.4 Variables declaradas global o nonlocal


Si a una variable no se le asigna valor en una función, Python la considera libre y busca su valor
en los niveles superiores de esa función, empezando por el inmediatamente superior y continuando
hasta el programa principal.
Si a la variable se le asigna valor en algún nivel intermedio la variable se considera no local y
si se le asigna en el programa principal la variable se considera global, como muestran los
siguientes ejemplos.
En el programa de la figura 3.18 la variable se declara como global, para que su valor sea el del
programa principal. La ejecución del mismo se muestra en la figura 3.19.

 116 
Figura 3.18 Variable global Figura 3.19 Resultado al ejecutar el programa
En el programa de la figura 3.20 la variable se declara como nonlocal, para que su valor sea el
de la función intermedia. Su ejecución se tiene en la figura 3.21.

Figura 3.20 Variable nonlocal Figura 3.21 Resultado al ejecutar el programa


Si a una variable declarada global o nonlocal en una función no se le asigna valor en el nivel
superior correspondiente, Python dará un error de sintaxis, como muestra el programa de la figura
3.22 en su ejecución (figura 3.23).

Figura 3.22 Variable nonlocal no definida Figura 3.23 Resultado al ejecutar el programa

 117 
3.3 Argumentos y devolución de valores

Las funciones en Python admiten argumentos en su llamada y permiten devolver valores. Estas
posibilidades permiten crear funciones más útiles y fácilmente reutilizables. En este apartado se
muestran estos conceptos mediante varios ejemplos. En ellos, no se pretende encontrar la mejor
solución al problema planteado, sino simplemente introducir los conceptos de argumentos y
devolución de valores.
Aunque las funciones en Python pueden acceder a cualquier variable del programa
declarándolas como variables globales o no locales, se necesita saber el nombre de las variables,
como muestra el programa de la figura 3.24. Mientras que la ejecución del mismo se presenta en
la figura 3.25.

Figura 3.24 Utilizando una función Figura 3.25 Resultado al ejecutar el programa
El problema de una función de este tipo es que es muy difícil de reutilizar en otros programas o
incluso en el mismo programa, ya que sólo es capaz de hacer la media de las variables a y b. Si en
el programa no se utilizan esos nombres de variables, la función no funcionaría.
Para evitar ese problema, las funciones admiten argumentos, es decir, permiten que se les envíen
valores con los que trabajar. De esa manera, las funciones se pueden reutilizar más fácilmente,
como muestra el programa de la figura 3.26. Su ejecución se observa en la figura 3.27.

Figura 3.26 Mejorando la función Figura 3.27 Resultado al ejecutar el programa

 118 
Esta función tiene todavía un inconveniente. Como las variables locales de una función son
inaccesibles desde los niveles superiores, el programa principal no puede utilizar la variable media
calculada por la función y tiene que ser la función la que escriba el valor, eso complica su
reutilización, porque aunque es probable que en otro programa nos interese una función que calcule
la media, es más difícil que nos interese que escriba el valor nada más calcularlo.
Para evitar ese problema, las funciones pueden devolver valores, es decir, pueden enviar valores
al programa o función de nivel superior, los mismos pueden ser asignados a una o varias variables.
De esa manera, las funciones se pueden reutilizar más fácilmente, como muestra el programa de la
figura 3.28. Su ejecución se observa en la figura 3.29.
Esta función puede ser utilizada con más flexibilidad que la de la figura 3.26, puesto que el
programador puede elegir qué hacer con el valor calculado por la función.

Figura 3.28 Otra versión de la función Figura 3.29 Resultado al ejecutar el programa
Esta función tiene todavía un inconveniente y es que sólo calcula la media de dos valores. Sería
más interesante que la función calculara la media de cualquier cantidad de valores. Para evitar ese
problema, las funciones pueden admitir una cantidad indeterminada de valores, tal como se verá
en el siguiente apartado.

3.3.1 Argumentos indeterminados


Al ser un lenguaje interpretado Python presenta mucha flexibilidad. Quizá en alguna ocasión no
se conoce de antemano cuántos elementos se van a enviar a una función. En estos casos se pueden
utilizar los argumentos indeterminados por posición y por nombre.

3.3.1.1 Argumentos por posición


Para evitar el problema del programa de la figura 3.28, y que la función pueda admitir una
cantidad indeterminada de argumentos, se utiliza la expresión *args, esto se conoce por

 119 
argumentos por posición. Su uso se muestra el programa de la figura 3.30. La ejecución del mismo
se observa en la figura 3.31.

Figura 3.30 Calculando la media de varios valores Figura 3.31 Resultado al ejecutar el programa
Esta última función puede ser utilizada con más flexibilidad que las vistas anteriormente, puesto
que el programador puede elegir de cuántos valores hacer la media y qué hacer con el valor
calculado por la función.
El signo asterisco (*) es utilizado para indicar dicha funcionalidad; de lo contrario, únicamente
el primer argumento sería almacenado en args.
Dado que todos los argumentos serán guardados en el primer parámetro (args), Python mostrará
un mensaje de error al intentar especificar algún otro luego de éste. Por lo que si se utilizan
argumentos fijos e indeterminados simultáneamente como argumentos en una función, primero se
escriben los fijos y luego los indeterminados. Un ejemplo de este error su muestra al ejecutar el
programa de la figura 3.32 en la figura 3.33.

Figura 3.32 Argumentos indeterminados y Figura 3.33 Resultado al ejecutar el programa


fijos enviados de forma incorrecta

 120 
Para corregir este error basta con cambiar el orden de los argumentos, escribiendo primero los
fijos y luego los indeterminados, tal como se muestra en el programa de la figura 3.34. El resultado
de su ejecución se muestra en la figura 3.35.

Figura 3.34 Argumentos fijos e indeterminados Figura 3.35 Resultado al ejecutar el programa
enviados de forma correcta
También las funciones pueden devolver varios valores simultáneamente, asignándolos a varias
variables, como muestra el programa de la figura 3.36. La ejecución del mismo se observa en la
figura 3.37.

Figura 3.36 Devolviendo varios valores Figura 3.37 Resultado al ejecutar el


programa
Es importante señalar que se pueden enviar diversos tipos de datos al mismo tiempo como
argumentos indeterminados por posición. Esto se muestra en el programa de la figura 3.38 y su
ejecución en la figura 3.39.

 121 
Figura 3.38 Argumentos indeterminados de varios Figura 3.39 Resultado al ejecutar el programa
tipos

3.3.1.2 Argumentos por nombre


Este tipo de argumentos se funcionan de forma análoga a los argumentos por posición, también
se conocen como keyword arguments, y son representados con dos asteriscos (**) y el nombre
kwargs. Cabe destacar que los nombres de estos argumentos son indiferentes; args y kwargs son
utilizados simplemente por convención.
En este caso kwargs es un diccionario (más adelante se verá este concepto) que contiene el
nombre de cada uno de los argumentos junto con su valor. Siendo esto así, el orden de los mismos
es indistinto.
Las claves de este diccionario serían los nombres de los argumentos indicados al llamar a la
función y los valores del diccionario, los valores asociados a estos argumentos. La forma en cómo
se envían este tipo de argumentos se muestran en el programa de la figura 3.40 y su ejecución se
observa en la figura 3.41. Aquí se ve que cada valor de los argumentos está asociado directamente
con su nombre.

Figura 3.40 Argumentos indeterminados por nombre Figura 3.41 Resultado al ejecutar el
programa
Para entender un poco más de dichos argumentos se verán dos programas para calcular cierto
importa al cual que se le hace un 10% de descuento. El primero (figura 3.42) lo hace utilizando
argumentos indeterminados por posición. Su ejecución se muestra en la figura 3.43.

 122 
Figura 3.42 Calculando en descuento de un importe con Figura 3.43 Resultado al ejecutar el
argumentos indeterminados por posición programa
El segundo lo hace utilizando argumentos indeterminados por nombre (figura 3.44) y como se
observa en su ejecución (figura 3.45) da el mismo resultado que el de la figura 3.43.
En este caso los nombres de los argumentos indeterminados por nombre tienen el valor asignado
junto con el nombre del argumento, esto por ser valores del diccionario, esto al momento de llamar
a la función.
No importa si están en diferentes posiciones en el diccionario al momento de llamar a la función
con respecto a lo de los argumentos en los nombre de las variables al definir la función, también
esto se muestra en la figura 3.44. Lo único es que deben coincidir los nombres de los argumentos
en ambos casos.

Figura 3.44 Calculando en descuento de un importe con Figura 3.45 Resultado al ejecutar el
argumentos indeterminados por nombre programa
Además ambos tipos de argumentos pueden ser implementados en una misma función como
excepción al error de sintaxis. En la figura 3.46 se muestra un programa donde se combinas
argumentos indeterminados tanto por posición como por nombre. Su ejecución se observa en la
figura 3.47.

 123 
Figura 3.46 Combinando argumentos indeterminados Figura 3.47 Resultado al ejecutar el
programa

3.3.2 Argumentos por valor y por referencia


En los lenguajes en los que las variables son "cajas" en las que se guardan valores, cuando se
envía una variable como argumento en una llamada a una función suelen existir dos posibilidades:
 paso por valor: se envía simplemente el valor de la variable, en cuyo caso la función no puede
modificar la variable, pues la función sólo conoce su valor, pero no la variable que lo
almacenaba.
 paso por referencia: se envía la dirección de memoria de la variable, en cuyo caso la función sí
que puede modificar la variable.
En Python no se hace ni una cosa ni otra. En Python cuando se envía una variable como
argumento en una llamada a una función lo que se envía es la referencia al objeto al que hace
referencia la variable. Dependiendo de si el objeto es mutable o inmutable, la función podrá
modificar o no el objeto.
Si se quiere modificar el valor de uno de los argumentos y que estos cambios se reflejaran fuera
de la función se tendría que pasar el parámetro por referencia.
En C los argumentos de las funciones se pasan por valor, aunque se puede simular el paso por
referencia usando punteros. En Java también se usa paso por valor, aunque para las variables que
son objetos lo que se hace es pasar por valor la referencia al objeto, por lo que en realidad parece
paso por referencia.
En Python también se utiliza el paso por valor de referencias a objetos, como en Java, aunque
en el caso de Python, a diferencia de Java, todo es un objeto (para ser exactos lo que ocurre en
realidad es que al objeto se le asigna otra etiqueta o nombre en el espacio de nombres local de la
función).

 124 
Sin embargo no todos los cambios que se haga a los argumentos dentro de una función Python
se reflejarán fuera de esta, ya que hay que tener en cuenta que en Python existen objetos inmutables,
como las listas, por lo que si intentáramos modificar una lista pasada como parámetro lo que
ocurriría en realidad es que se crearía una nueva instancia, por lo que los cambios no se verían
fuera de la función.
Un ejemplo de esto se muestra en el programa de la figura 3.48. El resultado de la ejecución de
este programa se muestra en la figura 3.49.

Figura 3.48 Pasando valores a una función Figura 3.49 Resultado al ejecutar el
programa
Como se ve, la variable x no conserva los cambios una vez salimos de la función porque los
enteros son inmutables en Python. Sin embargo la variable y si los conserva, porque las listas son
mutables.
En resumen: los valores mutables se comportan como paso por referencia, y los inmutables
como paso por valor.

3.4 Funciones recursivas

Primeramente hay que definir que es la recursividad en computación: proceso mediante el que
una función se llama a sí misma de forma repetida, hasta que se satisface alguna determinada
condición.
El proceso se utiliza para computaciones repetidas en las que cada acción se determina mediante
un resultado anterior. Se pueden escribir de esta forma muchos problemas iterativos.
Python admite las llamadas recursivas, permitiendo a una función, llamarse a sí misma, de igual
forma que lo hace cuando llama a otra función.

 125 
En la figura 3.50 se muestra un programa el cual se llama así mismo, dicho programa obtiene el
factorial de un número de forma recursiva, esto se puede realizar porque el factorial se puede definir
de forma recursiva. En la figura 3.51 se tiene el resultado al ejecutar dicho programa.

Figura 3.50 Obteniendo el factorial de forma recursiva Figura 3.51 Resultado al ejecutar el
programa
Sería importante recordar cómo se define primeramente el factorial:
n! = n  (n1)  (n2)  …  3  2  1
Ahora hay que recordar cómo se define el factorial de forma recursiva:
Si n > 0 n! = n  (n1)!
Al desarrollar dicha expresión se tiene que:
n! = n  (n1)!
= n  (n1)  (n2)!
= n  (n1)  (n2)  (n3)!

= n  (n1)  (n2)  (n3)  …  3  2!
= n  (n1)  (n2)  (n3)  …  3  2  1!
= n  (n1)  (n2)  (n3)  …  3  2  1
Como se observa, para definir el factorial es necesario utilizar el mismo factorial, es decir
utilizarse a sí mismo.
Las funciones recursivas funcionan de forma similar a las iteraciones, y se debe de planificar el
momento en que una función recursiva deja de llamarse o se tendrá una función recursiva infinita.
En cualquier lenguaje de programación, incluyendo Python, se deben satisfacer dos condiciones
para que se pueda resolver un problema recursivamente:
Primera: El problema se debe escribir en forma recursiva.

 126 
Segunda: La estructura de control del problema debe incluir una condición de fin.
Las funciones recursivas suelen ser muy útiles en casos muy puntuales, pero debido a su gran
factibilidad de caer en iteraciones infinitas, deben extremarse las medidas preventivas adecuadas
y, solo utilizarse cuando sea estrictamente necesario y no exista una forma alternativa viable, que
resuelva el problema evitando la recursividad.
En la figura 3.52 se tiene otro programa en el cual se utiliza la recursividad. Un resultado al
ejecutarlo se muestra en la figura 3.53.

Figura 3.52 Otra función recursiva Figura 3.53 Resultado posible al ejecutar
el programa

3.5 Generadores

Los generadores son funciones que permiten obtener sus resultados poco a poco. Es decir, cada
vez que llamemos a la función nos darán un nuevo resultado. Por ejemplo, una función para generar
todos los números pares que cada vez que la llamemos nos devuelva el siguiente número par. ¿Se
puede construir una función que nos devuelva todos los números pares? Esto no es posible si no
usamos generadores. Como se sabe los números pares son infinitos.

3.5.1 ¿Para qué sirven y cómo se construyen los generadores?


Pues, como el propio nombre indica, para generar datos en tiempo de ejecución. Además
también se pueden acelerar búsquedas y crear ciclos más rápidos.

 127 
Para construir generadores sólo se tienen que usar la orden yield. Esta orden devolverá un valor
(igual que hace return) pero, además, congelará la ejecución de la función hasta la próxima vez
que le pidamos un valor.

3.5.2 Utilizando generadores


La mejor forma de entenderlo es creando uno. En el programa de la 3.54 la figura 3.54 se tiene
un generador que devuelva números pares. Su resultado se muestra en la figura 3.55.

Figura 3.54 Utilizando yield Figura 3.55 Resultado al ejecutar el


programa
Lo que hace yield entonces es:
• La primera vez que corre (primera vez en la invocación a la función principal, pares() en este
caso), retorna inmediatamente - pero no retorna el elemento index*2 sino un objeto
(generador) que guarda el estado de la función, congelado justo antes del yield.
• Cada vez que se ejecuta el next(), la función sale del estado congelado hasta que encuentra
el próximo yield (incluido el primero), en cuyo caso retorna el elemento (ahora sí, el
argumento del yield), y vuelve a congelarse, o bien llega al fin de la función.
Otro ejemplo del uso de yield es el programa de la figura 3.56, el cual genera números primos.
Su ejecución se muestra en la figura 3.57.

 128 
Figura 3.56 Utilizando nuevamente yield Figura 3.57 Resultado al ejecutar el
programa
Se puede utilizar range para genera todos los valores del rango. El programa de figura 3.58
muestra su uso. La ejecución de programa se tiene en la figura 3.59.

Figura 3.58 Utilizando range Figura 3.59 Resultado al ejecutar el programa


Si se hacen más llamadas next() al valor del rango o a la cantidad de iteraciones del ciclo se
muestra un mensaje de error, tal como el que se produce al ejecutar el programa de la figura 3.60.
La ejecución del mismo se muestra en la figura 3.61.

 129 
Figura 3.60 Error al utilizar yield Figura 3.61 Resultado al ejecutar el programa
Se puede ver que después de rendir todos los valores next() causó el error StopIteration.
Básicamente este error informa que todos los valores han sido procesados. Se puede preguntar ¿por
qué no se recibe este error mientras se utiliza un ciclo for? Bueno, la respuesta es simple. El ciclo
for captura automáticamente este error y deja de llamar al siguiente.
Y además ¿por qué el programa se detiene en la segunda llamada next() si el rango es 1,3. La
función range() por default inicia en 0. Si el valor del rango fuera 3 sus valores serían [0, 1, 2],
pero se indicó que iniciará en 1, por eso sus valores son [1, 2]. Para entender más la función range(),
ver el programa de la figura 3.62. Su ejecución se muestra en la figura 3.63.

Figura 3.62 Diferentes rangos Figura 3.63 Resultado al ejecutar el programa


Cuando se reanuda la ejecución llamando a uno de los métodos del generador, como es el caso
de next(), la función puede proceder exactamente como si la expresión yield fuera sólo otra llamada
externa. El valor de la expresión de yield después de la reanudación depende del método que
reanudó la ejecución.

 130 
3.6 Funciones integradas

Python trae consigo ciertas funciones que vienen por default y están siempre disponible, esto
es, no es necesario cargarlas desde ningún módulo, como input() o abs(). Dichas funciones
dependen de la versión Python que se tenga instalada. Dichas funciones se conocen como built-in
Functions o funciones integradas.
En la versión 3.x de Python las funciones integradas, por orden alfabético, se muestran en la
tabla 3.1.
Tabla 3.1 Funciones integras en Python 3.x

Built-in Functions (funciones integradas)


abs() dict() help() min() setattr()
all() dir() hex() next() slice()
any() divmod() id() object() sorted()
ascii() enumerate() input() oct() staticmethod()
bin() eval() int() open() str()
bool() exec() isinstance() ord() sum()
bytearray() filter() issubclass() pow() super()
bytes() float() iter() print() tuple()
callable() format() len() property() type()
chr() frozenset() list() range() vars()
classmethod() getattr() locals() repr() zip()
compile() globals() map() reversed() __import__()
complex() hasattr() max() round()
delattr() hash() memoryview() set()

A continuación de describe brevemente cada una de estas funciones.


abs(x)
Devuelve el valor absoluto de un número. El argumento puede ser un entero normal o largo o
un número de coma flotante. Si el argumento es un número complejo, se devuelve su módulo.
all(iterable)
Devuelve true si todos los elementos del iterable son verdaderos (o si el iterable está vacío).

 131 
any(iterable)
Devuelve true si algún elemento de iterable es verdadero. Si el iterable está vacío, devuelve
false.
ascii(object)
Como repr(), devuelve una cadena que contiene una representación imprimible de un objeto,
pero escapa de los caracteres no ASCII de la cadena devuelta por repr() utilizando \ x, \ u o \ U.
bin(x)
Convierta un número entero en una cadena binaria prefijada con "0b". El resultado es una
expresión válida de Python. Si x no es un objeto int de Python, tiene que definir un método __index
__ () que devuelve un entero.
class bool([x])
Devuelve un valor booleano. x se convierte usando el procedimiento estándar de verificación de
la verdad. Si x es falso u omitido, esto devuelve falso; De lo contrario devuelve true. La clase bool
es una subclase de int.
class bytearray([fuente[,codificación[, errores]]])
Devuelve una nueva matriz de bytes. La clase bytearray es una secuencia mutable de enteros en
el rango 0  x < 256. Tiene la mayoría de los métodos habituales de secuencias mutables, descritos
en Mutable Sequence Types, así como la mayoría de los métodos que tiene el tipo bytes.
class bytes ([fuente[,codificación[, errores]]])
Devuelve un nuevo objeto bytes, que es una secuencia inmutable de enteros en el rango
0x<256. bytes es una versión inmutable de bytearray, tiene los mismos métodos no mutantes y
el mismo comportamiento de indexación y corte.
callable(object)
Devuelve true si el argumento object parece tener una interfaz de llamadas (como las funciones
y métodos) y false en caso contrario. Si devuelve true, aún es posible que falle la llamada, pero si
es false, las llamadas a object siempre serán infructuosas
chr(i)
Devuelve una cadena de un carácter cuyo código ASCII es el entero i, es decir, chr(97) devuelve
la cadena 'a'. Es la inversa de la función ord(). El argumento debe estar en el rango de 0 a 255,
ambos incluidos. Se tiene un mensaje de error si i está fuera de dicho rango.
classmethod(function)

 132 
Devuelve un método de clase para la función.
compile (string, filename, kind)
Compila la cadena string a un objeto código. Los objetos código pueden ejecutarse con la
función exec() y evaluarse en una llamada a eval(). El argumento filename debe proporcionar el
archivo del que se leyó el código. Pasar, por ejemplo, '<string>' si no se ha recuperado el código
de ningún archivo. El argumento kind específica qué tipo de código se ha de compilar.
complex(real[, imag])
Crea un número complejo con el valor real + imag*j o convierte una cadena o número a
complejo. Cada argumento puede ser de cualquier tipo numérico (incluso complejo). imag toma
un valor cero por omisión, y la función sirve de función de conversión como int(), long() y float();
en tal caso también acepta un argumento cadena, que debe representar un número complejo válido.
delattr(object, name)
Esta función es pariente de setattr(). Los argumentos son un objeto y una cadena. La cadena
debe ser el nombre de uno de los atributos del objeto. La función elimina dicho atributo, siempre
que el objeto lo permita.
class dict(**kwarg), class dict(mapping, **kwarg), class dict(iterable, **kwarg)
Crea un nuevo diccionario. El objeto dict es la clase de diccionario.
dir([object])
Sin argumentos, devuelve la lista de nombres de la tabla de símbolos local actual. Con
argumento, intenta recuperar una lista de atributos válidos para el objeto indicado
divmod (a, b)
Toma como argumentos dos números y devuelve una pareja de números: el primero es el
cociente de los argumentos y el segundo su resto. Si los operandos son de tipo mixto, se aplican
las reglas de operadores binarios aritméticos. En el caso de los enteros largos, el resultado equivale
a (a / b, a % b). En el caso de los números en coma flotante, el resultado es (q, a % b), donde q
suele ser math.floor(a / b), pero puede ser uno menos. En cualquier caso, q * b + a % b se acerca
mucho a a, si a % b no es cero y tiene el mismo signo que b, and 0  abs(a % b) < abs(b).
enumerate(iterable, start=0)
Devuelve un objeto enumerate. Iterable debe ser una secuencia, un iterador o algún otro objeto
que admita la iteración. El método __next __ () del iterador devuelto por enumerate() devuelve

 133 
una tupla que contiene un recuento (del inicio que toma por defecto 0) y los valores obtenidos de
iterar sobre iterable.
eval(expression[, globals[, locals]])
Los argumentos son una cadena y dos diccionarios opcionales. El argumento expression se
analiza y evalúa como expresión de Python (hablando técnicamente, una lista de condiciones)
usando los diccionarios globals y locals como espacio nominal global y local, respectivamente. Si
se omite el diccionario locals, toma por valor el diccionario globals.
exec(object[, globals[, locals]]
Esta función admite la ejecución dinámica del código Python. object debe ser una cadena o un
objeto de código. Si es una cadena, la cadena se analiza como un conjunto de instrucciones Python
que luego se ejecuta. Si es un objeto de código, simplemente se ejecuta.
filter(function, list)
Construye una lista a partir de los elementos de list para los cuales la función function devuelve
un valor verdadero. Si list es una cadena o una tupla, el resultado tiene ese tipo también; en caso
contrario es una lista. Si function es none, se presupone la función identidad, por lo que se eliminan
todos los elementos falsos (cero, nulo o vacío) de list.
float(x)
Convierte una cadena o número a coma flotante. Si el argumento es una cadena, debe contener
una representación válida de un número en coma flotante, con espacio en blanco alrededor
opcionalmente. En caso contrario, el argumento puede ser un entero normal o largo, y se devuelve
un número de coma flotante del mismo valor (dentro de la precisión de coma flotante de Python).
format(value[, format_spec])
Convierta un valor a una representación "formateada", como lo controla format_spec. La
interpretación de format_spec dependerá del tipo del argumento value, sin embargo existe una
sintaxis de formato estándar que es utilizada por la mayoría de los tipos incorporados.
frozenset([iterable])
Devuelve un nuevo objeto frozenset, opcionalmente con elementos tomados de iterables.
getattr(object, name[, default])
Devuelve el valor del atributo denominado name de object. name debe ser una cadena de uno
de los atributos del objeto, siendo el resultado el valor de dicho atributo.
globals()

 134 
Devuelve un diccionario que representa la tabla global de símbolos actual. Éste es siempre el
diccionario del módulo actual.
hasattr(object, name)
Los argumentos son un objeto y una cadena. El resultado es 1 si la cadena es el nombre de uno
de los atributos del objeto o 0 en caso contrario (se implementa llamando a getattr(object, name),
mirando si hace saltar una excepción o no).
hash(object)
Devuelve el valor hash del objeto (si lo tuviere). Los valores hash son enteros que se utilizan
para comparar claves de diccionario de manera rápida en las búsquedas. Los valores numéricos
que resultan iguales en una comparación tienen el mismo valor hash (aun si son de tipos diferentes,
como 1 y 1.0).
help([object])
Invoca el sistema de ayuda incorporado. (Esta función está destinada al uso interactivo.) Si no
se presenta ningún argumento, el sistema de ayuda interactivo se inicia en la consola del intérprete.
Si el argumento es una cadena, la cadena se busca como el nombre de un módulo, función, clase,
método, palabra clave o tema de documentación y se imprime una página de ayuda en la consola.
Si el argumento es cualquier otro tipo de objeto, se genera una página de ayuda en el objeto.
hex(x)
Convierte un número entero (de cualquier tamaño) a una cadena hexadecimal. El resultado es
una expresión Python válida. Esta función siempre devuelve un literal sin signo.
id(object)
Devuelve el identificador de un objeto. Es un entero (o entero largo) que cumple ser único y
constante durante toda la vida del objeto. Dos objetos cuya vida no coincida en el tiempo pueden
compartir el mismo valor de id(). Devuelve la dirección en memoria del objeto.
input([prompt])
Si el argumento prompt está presente, se escribe en la salida estándar sin una nueva línea de
arrastre. La función entonces lee una línea de la entrada, la convierte en una cadena (quitando una
nueva línea de arrastre), y devuelve eso. Cuando EOF es leido, EOFError se muestra.
class int(x=0), class int(x, base=10)
Devuelve un objeto entero construido a partir de un número o cadena x, o devuelve 0 si no se
dan argumentos. Si x es un número, devuelve x .__ int __ ().

 135 
isinstance(object, class)
Devuelve verdadero si el argumento object es una instancia del argumento class o de una de sus
subclases. También devuelve verdadero si class es un objeto tipo y object es un objeto de este tipo.
Si object no es una instancia de clase u objeto del tipo indicados, devuelve falso. Si class no es ni
un objeto de una clase ni de un tipo, se lanza una excepción TypeError.
issubclass(class1, class2)
Devuelve verdadero si class1 es una subclase (directa o indirecta) de class2. Una clase se
considera subclase de sí misma. Si alguno de los dos argumentos no es un objeto clase, se lanza
una excepción TypeError.
Iter(object, sentinel)
Devuelve un objeto iterador. El primer argumento se interpreta de manera muy diferente
dependiendo de la presencia del segundo argumento. Sin un segundo argumento, el object debe ser
un objeto de colección que soporte el protocolo de iteración (el método __iter __ ()), o debe soportar
el protocolo de secuencia (el método __getitem __ () con argumentos enteros comenzando en 0).
len(s)
Devuelve la longitud (el número de elementos) de un objeto. El argumento puede ser una
secuencia (cadena, tupla o lista) o una correspondencia (diccionario).
class list([iterable])
En lugar de ser una función, la lista es en realidad un tipo de secuencia mutable, tal como se
documenta en Listas y Tipos de Secuencia - list, tuple, range.
locals()
Devuelve un diccionario que representa la tabla de símbolos local actual. Advertencia: No debe
modificarse el contenido de este diccionario. Los cambios pueden no afectar a las variables locales
del intérprete.
map(function, list, ...)
Aplica function a cada elemento de list y devuelve una lista con los resultados. Si se pasan
argumentos adicionales list, function debe tomar tantos argumentos como listas haya y se aplica la
función en paralelo sobre todos los elementos de la misma posición de todas las listas argumento.
max(iterable, *[, key, default]), max(arg1, arg2, *args[, key])
Devuelve el mayor elemento de una secuencia no vacía. Si hay más de una argumento, devuelve
el mayor de los argumentos.

 136 
memoryview(obj)
Devuelve un objeto de "vista de memoria" creado a partir del argumento dado. Consultar Vistas de
memoria para obtener más información:
https://docs.python.org/3/library/stdtypes.html#typememoryview
min(iterable, *[, key, default]), min(arg1, arg2, *args[, key])
Devuelve el menor elemento de una secuencia no vacía. Si hay más de una argumento, devuelve
el menor de los argumentos.
next (iterador [, default])
Devuelve el siguiente elemento del iterador llamando a su método __next __ (). Si se da el
default, este es retornado si el iterador se agota, de lo contrario StopIteration será mostrado.
class object()
Devuelve un nuevo objeto sin características. El objeto es una base para todas las clases. Tiene
los métodos que son comunes a todas las instancias de las clases de Python. Esta función no acepta
ningún argumento.
oct(x)
Convierta un número entero en una cadena octal prefijada con "0o". El resultado es una
expresión válida de Python. Si x no es un objeto Python int, tiene que definir un método __index
__ () que devuelve un entero.
open(file, mode=’r’, buffering=-1, encoding=None, errors=None, newline=None, closefd=True,
opener=None)
Abre un archivo y devuelva un objeto de archivo correspondiente. Si no se puede abrir el
archivo, se genera un OSError. File es un objeto path-like que da el pathname (absoluto o relativo
al directorio de trabajo actual) del archivo que se va a abrir o un descriptor de archivo entero del
archivo que se va a envolver. (Si se da un descriptor de archivo, se cierra cuando el objeto de E/S
devuelto está cerrado, a menos que closefd esté establecido en Falso.)
ord(c)
Dada una cadena que representa un carácter Unicode, devuelve un entero que representa el punto
de código Unicode de ese carácter.
pow(x, y[, z])

 137 
Devuelve x elevado a y; si se proporciona z, devuelve x elevado a y, módulo z (calculado de
manera más eficaz que pow(x, y) % z). Los argumentos deben ser de tipo numérico. Si los tipos
son mixtos, se aplican las reglas de operadores binarios aritméticos habituales.
print(* objects, sep = “”, end = “\ n”, file = sys.stdout, flush = False)
Imprime objetos en el archivo de secuencia de texto, separados por sep y seguidos por el end.
sep, end, file y flush, si están presentes, deben darse como argumentos de palabra clave.
Todos los argumentos que no son de palabras clave se convierten en cadenas como str() y
escritas en el flujo, separadas por sep y seguidas por end. Ambos sep y end deben ser cadenas;
también pueden ser none, lo que significa utilizar los valores predeterminados. Si no se dan objetos,
print() solo regresa end.
class property(fget=None, fset=None, fdel=None, doc=None)
Devuelve un atributo de propiedad. fget es una función para obtener un valor de atributo. fset es
una función para establecer un valor de atributo. fdel es una función para eliminar un valor de
atributo. Y doc crea una docstring para el atributo.
range(stop), range(start, stop[, step])
Ésta es una función versátil para crear listas que contengan progresiones aritméticas. Su uso más
popular es en los ciclos for. Los argumentos deben ser enteros normales. Si se omite el argumento
step toma un valor de 1. Si se omite el argumento start toma un valor de 0. La forma completa
devuelve una lista de enteros normales [start, start + step, start + 2 * step,...]. Si step es positivo,
el último elemento es el mayor valor start + i * step menor que stop; si step es negativo, el último
elemento es el mayor valor start + i * step mayor que stop. step no debe ser cero (o se lanza
ValueError).
repr(objet)
Devuelve una cadena que contiene una representación imprimible de un objeto. Para muchos
tipos, esta función intenta devolver una cadena que producirá un objeto con el mismo valor cuando
se pasa a eval(), de lo contrario la representación es una cadena entre corchetes angulares que
contiene el nombre del tipo del objeto junto con información adicional incluyendo a menudo el
nombre y la dirección del objeto.
reversed(seq)

 138 
Devuelve un iterador inverso. seq debe ser un objeto que tiene un método __reversed __ () o
soporta el protocolo de secuencia (los métodos __len __ () y __getitem __ () con argumentos
enteros comenzando en 0).
round(number[, ndigits])
Retorna un número redondeado a precisión ndigits después del punto decimal. Si ndigits se
omite o es None, devuelve el entero más cercano a su entrada.
class set([iterable])
Devuelve un nuevo objeto set, opcionalmente con elementos tomados de iterable. set es una
clase incorporada.
setattr(objet, name, value)
Es la equivalente a getattr(). Los argumentos son un objeto, una cadena y un valor arbitrario.
La cadena puede nombrar un atributo existente o un atributo nuevo. La función asigna el valor al
atributo, siempre que el objeto lo permita.
class slice(stop), class slice(start, stop[, step])
Devuelve un objeto slice que representa el conjunto de índices especificado por range(start,
stop, step). Los argumentos start y step toman el valor por omisión de None. Los objetos slice
tienen atributos de sólo lectura start, stop y step que se limitan a devolver los valores de los
argumentos (o su valor por defecto). No tienen ninguna otra funcionalidad explícita, pero son
utilizados por Numerical Python (la extensión de cálculo matricial) y otras extensiones de terceros.
sorted (iterable, *, key = none, reverse = false)
Devuelve una nueva lista ordenada de los elementos en iterable. Tiene dos argumentos
opcionales que deben especificarse como argumentos de palabra clave. key especifica una función
de un argumento que se utiliza para extraer una clave de comparación de cada elemento de lista:
key = str.lower. El valor predeterminado es None (compara los elementos directamente). reverse
es un valor booleano. Si se establece en True, los elementos de lista se ordenan como si cada
comparación se invirtiera.
staticmethod(function)
Devuelve un método estático para la función. Un método estático no recibe un primer argumento
implícito.
class str(object=”), class str(object=b”, encoding=’utf-8’, errors=’strict’)

 139 
Devuelve una cadena que contiene una representación imprimible de un objeto. En el caso de
cadenas, devuelve la propia cadena.
sum(iterable[, start])
Las sumas comienzan en start en los elementos de un iterable de izquierda a derecha y devuelven
el total. El valor predeterminado de start es 0.
super([type[, object-or-type]])
Devuelve un objeto proxy que delega las llamadas de método padre o hermana de clase type.
Esto es útil para acceder a métodos heredados que han sido anulados en una clase. El orden de
búsqueda es el mismo que el utilizado por getattr() excepto que el tipo en sí se omite.
tuple ([iterable])
Devuelve una tupla cuyos elementos son los mismos que los de iterable en el mismo orden. Si
iterable ya es una tupla, se devuelve sin cambios. tuple es actualmente una secuencia de tipo
inmutable.
class type(object), class type(name, bases, dict)
Devuelve el tipo de object. El resultado es un objeto tipo. El módulo estándar types define
nombres para todos los tipos internos.
vars([object])
Sin argumentos, devuelve un diccionario correspondiente a la tabla de símbolos local actual.
Con un módulo, clase o instancia de clase como argumento (o cualquier cosa que tenga un atributo
__dict__ attribute), devuelve un diccionario correspondiente a la tabla de símbolos del objeto.
zip (*iterables)
Esta función devuelve una lista de tuplas, donde cada tupla contiene el i-ésimo elemento de cada
una de las secuencias de argumento. Se requiere al menos una secuencia, o se lanzará TypeError.
__import__(name, globals=None, locals=None, fromlist=(), level=0)
Nota: Esta es una función avanzada que no se necesita en la programación cotidiana de Python, a
diferencia de importlib.import_module().
Para ver a más detalle dichas funciones consultar en página oficial de Python el apartado de
funciones (https://docs.python.org/3/library/functions.html).

 140 
3.7 Actividades a realizar

Codificar y ejecutar en Python los programas para los problemas indicados en cada caso, además
de seguir las indicaciones y/o restricciones si las hubiera. En cada problema se muestran una o
varias figuras con posibles resultados de salida al ejecutar el programa. Todos los problemas deben
ser resueltos utilizando funciones.

a) Solicitar dos matrices y calcular su producto sin utilizar el método dot de numpy. Se deben
emplear al menos tres funciones. Una que solicite las dimensiones de las matrices, otra que
introduzca los valores y una más en la que se efectué la multiplicación. En la figura 3.64 se
muestran dos posibles resultados al ejecutar el programa.

Figura 3.64 Dos posibles resultados al ejecutar el programa

 141 
b) Solicitar dos matrices y calcular su suma sin utilizar la operación suma elemento a elemento de
matrices de numpy. Se deben emplear al menos tres funciones. Una que solicite las dimensiones
de las matrices, otra que introduzca los valores y una más en la que se efectué la suma. En la
figura 3.65 se muestran dos posibles resultados al ejecutar el programa.

Figura 3.65 Dos posibles resultados al ejecutar el programa


c) Solicitar dos matrices y calcular el producto elemento a elemento sin utilizar la operación
producto elemento a elemento de matrices de numpy. Se deben emplear al menos tres funciones.
Una que solicite las dimensiones de las matrices, otra que introduzca los valores y una más en
la que se efectué la multiplicación. En la figura 3.66 se muestran dos posibles resultados al
ejecutar el programa.

 142 
Figura 3.66 Dos posibles resultados al ejecutar el programa
d) Solicitar una matriz y calcular su transpuesta sin utilizar la función transpose() o el método .T
de numpy. Se deben emplear al menos tres funciones. Una que solicite las dimensiones de la
matriz, otra que introduzca los valores y una más en la que obtenga la transpuesta. En la figura
3.66 se muestran un posible resultado al ejecutar el programa.

Figura 3.67 Posibles resultado al ejecutar el programa

 143 
Para los siguientes programas crear cuatro matrices en archivos independientes con los valores
indicados en cada caso, tal como se muestra en la figura 6.68. Utilizar además las funciones o
métodos adecuados de numpy.

Figura 3.68 Posibles resultado al ejecutar el programa


e) Modificar el programa del inciso a) para leer los archivos de las matrices 1 y 2 y calcular su
multiplicación. Se deben emplear al menos cuatro funciones. Una que lea las matrices, otra las
redimensione correctamente de acuerdo a la cantidad de los valores del archivo, una que
compruebe si de acuerdo al redimensionado de las matrices estas cumplen con la condición para
poder multiplicarlas y una más en la que se efectué la multiplicación. Cuatro posibles resultados
al ejecutar el programa son mostrados en la figura 3.69.

 144 
Figura 3.69 Cuatro posibles resultados al ejecutar el programa
f) Modificar el programa del inciso b) para leer los archivos de las matrices 3 y 4 y calcular su
suma. Se deben emplear al menos cuatro funciones. Una que lea las matrices, otra las
redimensione correctamente de acuerdo a la cantidad de los valores del archivo, una que
compruebe si de acuerdo al redimensionado de las matrices estas cumplen con la condición para
poder sumarlas y una más en la que se efectué la suma. Cuatro posibles resultados al ejecutar el
programa son mostrados en la figura 3.70.

 145 
Figura 3.70 Cuatro posibles resultados al ejecutar el programa
g) Modificar el programa del inciso c) para leer los archivos de las matrices 3 y 4 y calcular su
producto elemento a elemento. Se deben emplear al menos cuatro funciones. Una que lea las
matrices, otra las redimensione correctamente de acuerdo a la cantidad de los valores del
archivo, una que compruebe si de acuerdo al redimensionado de las matrices estas cumplen con
la condición para poder multiplicarlas y una más en la que se efectué el producto elemento a
elemento. Cuatro posibles resultados al ejecutar el programa son mostrados en la figura 3.71.

 146 
Figura 3.71 Cuatro posibles resultados al ejecutar el programa
h) Modificar el programa del inciso d) para leer el archivo de la matriz 3 y calcular su transpuesta.
Se deben emplear al menos tres funciones. Una que lea la matriz, otra la redimensione
correctamente de acuerdo a la cantidad de los valores del archivo y una más en la que se calcule
la transpuesta. Tres posibles resultados al ejecutar el programa son mostrados en la figura 3.72.

Figura 3.72 Cuatro posibles resultados al ejecutar el programa

 147 
i) Solicitar una palabra o frase e identificar si la misma es o no un palíndromo (palabra o frase que
es leída iguales en ambas direcciones). Utilizar al menos tres funciones. La primera que solicite
la palabra o frase, la segunda que invierta la cadena y la tercer que las compara y verifique si es
un palíndromo. Se puede comprobar si el programa es correcto con la palabra RADAR o con la
frase DABALE ARROZ A LA ZORRA EL ABAD. Tres posibles resultados al ejecutar el
programa son mostrados en la figura 3.73.

Figura 3.73 Tres posibles resultados al ejecutar el programa


j) Realizar una pequeña calculadora de polinomios de segundo grado, con las siguientes opciones:
1. Suma de dos polinomios, 2. Producto de un polinomio por un escalar, 3. Opuesto del
polinomio, 4. Cálculo de las raíces del polinomio y 5. Salir. Las opciones deben estar en forma
de menú. El programa debe de regresar al menú después de haber mostrado el resultado
correspondiente. Solamente se podrá salir del programa utilizando la opción 5. Después de que
se introduzcan los coeficientes se deberá mostrar el polinomio resultante antes de hacer el
cálculo según la opción. Se deben introducir valores enteros solamente (positivos o negativos).
También se debe formatear el polinomio, es decir, generalmente se puede presentar el polinomio
como +5x2 + 3x + 2, debiendo ser 5x2  3x  2. También el polinomio resultante debe estar
formateado. Para el cálculo de las raíces se puede utilizar el programa del problema 2.8.2.h). Se
debe utilizar una función para cada opción, y una más para solicitar el polinomio y una más para
formatear es polinomio. Además se deben utilizar argumentos indeterminados para enviar los
valores a las funciones. Varios posibles resultados al ejecutar el programa son mostrados en la
figura 3.74.

 148 
Figura 3.74 Varios posibles resultados al ejecutar el programa

 149 
Unidad 4 Matemática simbólica
4.1 Introducción al Cálculo Simbólico en Python con sympy

Para trabajar Python como un CAS (Computer Algebra System, Sistema de Álgebra
Computacional), es necesario descargar e instalar el módulo sympy, esto se vio cómo hacerlo en la
primera unidad.
sympy es una biblioteca escrita en Python cuyo objetivo es reunir todas las características de un
sistema de álgebra computacional, ser fácilmente extensible y mantener el código todo lo simple
que sea posible. No requiere ninguna biblioteca externa, salvo para soporte gráfico. En su
funcionalidad podemos distinguir entre: manejo de enteros de precisión arbitraria y de números
racionales; simplificación básica, expansión, sustitución básica; manejo de funciones sobre el
cuerpo de los complejos; derivación, expansión en series de Taylor; límites, integración,
divisibilidad y factorización de polinomios; resolución de ecuaciones algebraicas, diferenciales y
sistemas; operaciones con matrices simbólicas, etc.
sympy define tres tipos numéricos: Real, Racional y Entero. La clase Racional representa un
número racional como una pareja de números enteros: el numerador y el denominador, de esta
forma Rational(1,2) representa 1/2, Rational(5,2) 5/2, etc. En el programa de la figura 4.1 se
muestra el uso de la clase Rational, mientras que el resultado se observa en la figura 4.2

Figura 4.1 Clase Rational Figura 4.2 Resultado al ejecutar el programa

4.1.1 Precisión arbitraria


sympy, como buen CAS que es, ofrece precisión arbitraria para sus tipos numéricos. Al contrario
que los números almacenados en coma flotante, al utilizar precisión arbitraria se puede conseguir
un resultado numérico con un número arbitrario de cifras decimales exactas. Para esto sympy
utiliza la biblioteca mpmath, escrita en Python, que se ejecuta en segundo plano (background), lo
que hace posible ejecutar cálculos usando aritmética con precisión arbitraria. De esta forma,

 150 
algunas constantes especiales como e, pi, oo (Infinito), son tratadas como símbolos y pueden ser
evaluadas con precisión arbitraria.
Para pasar de un resultado simbólico a uno numérico con cualquier número de decimales se
utilizan las funciones N() o .evalf(), que son equivalentes. En el programa de la figura 4.3 se tiene
un programa que muestra el uso de dichas funciones. En la figura 4.4 se muestra el resultado al
ejecutarlo.

Figura 4.3 Uso de la funciones N() o .evalf() Figura 4.4 Resultado al ejecutar el programa
Como puedes ver, evalf evalua la expresión como un número decimal. No obstante, hay que
tener cuidado porque si se utilizan los tipos nativos de Python no se puede manejar precisión
arbitraria o directamente se podría obtener resultados erróneos, como es el caso de la división
entera. Esto se muestra en el programa de la 4.5. Su ejecución se observa en la figura 4.6.

Figura 4.5 Precisión arbitraria en división Figura 4.6 Resultado al ejecutar el programa
entera
También existe una clase para representar el infinito (matemático) llamada oo, un ejemplo de
su uso de muestra en el programa de la figura 4.8, mientras que el resultado de su ejecución en la
figura 4.8

Figura 4.7 Utilizando infinito Figura 4.8 Resultado al ejecutar el programa

 151 
4.1.2 Simplificación numérica
También se puede hacer el proceso inverso al visto previamente, es decir, dado un número
decimal, tratar de buscar una representación simbólica del mismo. Esto se puede hacer con la
función nsimplify().
Esta función intenta encontrar una fórmula que sea numéricamente igual a la entrada dada. Esta
característica se puede utilizar para adivinar una fórmula exacta para una entrada aproximada de
punto flotante, o para adivinar una fórmula más simple para una entrada simbólica complicada.
El algoritmo utilizado por nsimplify es capaz de identificar fracciones simples, expresiones
algebraicas simples, combinaciones lineales de constantes dadas, y ciertas transformaciones
funcionales elementales de cualquiera de las precedentes.
Opcionalmente, se puede pasar nsimplify una lista de constantes a incluir (por ejemplo pi) y
una tolerancia numérica mínima. En el programa de la figura 4.9 hay algunos ejemplos elementales.
El resultado de su ejecución se muestra en la figura 4.10.

Figura 4.9 Utilizando nsimplify() Figura 4.10 Resultado al


ejecutar el programa
En la figura 4.11 se tiene un programa en el que se muestran varios ejemplos más avanzados del
uso de nsimplify(). El resultado de la ejecución del mismo se observa en la figura 4.12.

 152 
Figura 4.11 Utilizando nsimplify() Figura 4.12 Resultado al
ejecutar el programa

4.1.3 Variables simbólicas


En contraste a otros sistemas de álgebra computacional, en sympy hay que declarar las variables
simbólicas de forma explícita. Para hacerlo se utiliza la función Symbol(), tal como se muestra en
el programa de la figura 4.13.

Figura 4.13 Definiendo variables simbólicas


Después de declararlas podrán ser usadas, como se muestra en el programa de la figura 4.14. La
ejecución del mismo se observa en la figura 4.15.

Figura 4.14 Utilizando variables simbólicas Figura 4.15 Resultado al ejecutar el programa
Las variables simbólicas, ahora, pueden ser manipulados usando algunos de los operadores
Python: +, , *, **, and, or, not, etc.

 153 
El alma del Cálculo Simbólico son, naturalmente, las variables simbólicas, que en sympy son
instancias de la clase Symbol. Una explicación intuitiva sería que, mientras que las variables
ordinarias tienen un valor que puede ser un número, una cadena, un valor True/False, una
secuencia, etc. las variables simbólicas juegan el papel de "contenedores": no se sabe a priori lo
que pueden ser.
Además, en Python cuando se trabaja con sympy, se pueden hacer asignaciones múltiples de
variables simbólicas utilizando la función symbols(), así como asignarles un tipo de dato. Un
ejemplo de dicho tipo de asignación se muestra en el programa de la figura 4.16. Mientras que el
resultado al ejecutarlo se observa en la figura 4.17.

Figura 4.16 Asignaciones múltiples de variables Figura 4.17 Resultado al ejecutar el programa
simbólicas
Hay que analizar estas líneas:
 En sympy, todas las variables simbólicas que se vayan a utilizar se tienen que definir antes.
 Al definir una variable, se puede añadir una serie de suposiciones sobre ella (assumptions):
por ejemplo, se dice dicho que omega será de tipo real y que n será un número entero. Esto
es muy importante a la hora de trabajar.
 No se sabe cuánto vale omega ni cuánto vale t, y por tanto no se puede decir nada sobre su
coseno. Sin embargo, aunque no se sabe si n es 1, 5, 10 o -2, n es entero, por lo que el
segundo coseno valdrá 1 en todos los casos.

4.2 Manipulaciones de expresiones algebraicas

Para manipular expresiones algebraicas que involucren variables simbólicas en sympy hay dos
herramientas básicas: la sustitución y la simplificación y expansión las funciones.

 154 
4.2.1 Sustitución
Una de las cosas más comunes que usted podría querer hacer con una expresión matemática es
la sustitución. La sustitución sustituye todas las instancias de algo en una expresión por otra cosa.
Se realiza utilizando el método subs(). Por ejemplo en una expresión que quiere sustituir la
variables simbólica x por la variable simbólica y. La manera de se muestra en el programa de la
figura 4.18. El resultado de la ejecución del mismo se observa en la figura 4.19.

Figura 4.18 Utilizando el método subs() Figura 4.19 Resultado al ejecutar el programa
También es posible sustituir una variable simbólica por una subexpresión, o una subexpresión
por otra subexpresión o por una variable simbólica, tal como se muestra en el programa de la figura
4.20. El resultado de su ejecución se observa en la figura 4.21.

Figura 4.20 Utilizando el método subs() en Figura 4.21 Resultado al ejecutar el programa
varias ocasiones
La sustitución se hace generalmente por una de dos razones:
1. Evaluar una expresión en un punto determinado. Por ejemplo, si la expresión es cos(x) + 1
y se quiere evaluarla en el punto x = 0, para que se obtenga cos(0) + 1, que es 2. Tal como
se muestra en el programa de la figura 4.22. El resultado de su ejecución se observa en la
figura 4.23.

 155 
Figura 4.22 Evaluando una expresión Figura 4.23 Resultado al ejecutar el programa
utilizando el método subs()
2. Sustitución de una subexpresión por otra subexpresión. Hay dos razones por las que
queremos hacer esto:
a) La primera es si estamos tratando de construir una expresión que tiene cierta simetría,
como x**x**x**x. Para construir esto, se puede comenzar con x**y, y reemplazar y con
x**y. A continuación, obtener x**(x **y). Si reemplazamos y en esta nueva expresión
con x**x, obtendremos x**(x **(x**x)), la expresión deseada. Esto se muestra en el
programa de la figura 4.24. El resultado de su ejecución se observa en la figura 4.25.

Figura 4.24 Utilizando el método subs() en Figura 4.25 Resultado al ejecutar el programa
varias ocasiones
b) La segunda es si se quiere realizar una simplificación muy controlada, o tal vez una
simplificación que sympy es incapaz de hacer. Por ejemplo, se tiene sen(2x) + cos(2x),
y se quiere reemplazar sin(2x) por 2sin(x)cos(x). Como se verá, la función expand_trig()
hace esto. Sin embargo, esta función también expandirá cos(2x), que no se quiere. Si
bien hay maneras de realizar una simplificación tan precisa, una manera fácil es
simplemente reemplazar sin (2x) por 2sin(x)cos (x). Todo esto se muestra en el programa
de la figura 4.26. El resultado de su ejecución se observa en la figura 4.27.

 156 
Figura 4.26 Simplificando utilizando el método Figura 4.27 Resultado al ejecutar el
subs() programa
Hay dos cosas importantes que se deben tener en cuenta en el método subs(). Primero, devuelve
una nueva expresión. Los objetos sympy son inmutables. Esto significa que subs() no los modifica
en su lugar. Lo anterior se muestra en el programa de la figura 4.28, el resultado de su ejecución se
observa en la figura 4.29.

Figura 4.28 El método subs() no modifica los Figura 4.29 Resultado al ejecutar el programa
objetos
Aquí, se ve que al ejecutar expr.subs(x, 0) deja expr sin cambios. De hecho, puesto que las
expresiones de sympy son inmutables, ninguna función las cambiará en su lugar. Todas las
funciones devolverán nuevas expresiones.
La segunda es que para realizar múltiples evaluaciones a la vez, se da una lista de pares
(antiguos, nuevos) a subs(). Esto se muestra en el programa de la figura 4.30, el resultado de su
ejecución se observa en la figura 4.31.

Figura 4.30 Utilizando el método subs() en Figura 4.31 Resultado al ejecutar el programa
múltiples evaluaciones

 157 
4.2.2.1 Conversión de cadenas en expresiones sympy
La función sympify() (que es sympify, y no debe confundirse con simplify) se puede usar para
convertir cadenas en expresiones sympy. De cualquier manera se deben declarar las variables
simbólicas, de lo contrario se mostraría un mensaje de error. El uso de la sympyfy() se muestra en
el programa de la figura 4.32. El resultado de su ejecución se muestra en la figura 4.33.

Figura 4.32 Convirtiendo una cadena en una Figura 4.33 Resultado al ejecutar el programa
expresión sympy

4.2.2 Simplificación y expansión


Ahora se va a hace interesante a las matemáticas. Una de las características más útiles de un
sistema de algebra computacional es la capacidad de simplificar y expandir las expresiones
matemáticas. sympy tiene decenas de funciones para realizar diversos tipos de simplificación y
expansión.

4.2.2.1 Función simplify()


Hay una función general llamada simplify() que intenta simplificar todas las funciones de una
manera inteligente para llegar a la forma más simple de una expresión. En la figura 4.34 se muestra
un programa en el cual se hace uso de dicha función. El resultado de ejecutarlo se observa en la
figura 4.35.

 158 
Figura 4.34 Utilizando simplify() Figura 4.35 Resultado al ejecutar el programa
Pero simplify() tiene una problema. Simplemente aplica todas las operaciones de simplificación
principales en sympy y utiliza heurística para determinar el resultado más simple. Pero "más
simple" no es un término bien definido. Por ejemplo, se quiere "simplificar" x2+2x+1 pero Python
muestra la misma expresión en lugar de (x + 1)2. Esto se muestra en el programa de la figura 4.36.
El resultado de su ejecución se observa en la figura 4.37.

Figura 4.36 Resultado no deseado con simplify() Figura 4.37 Resultado al ejecutar el programa
Como se ve no se consigue lo que se quiere. Hay una función para realizar esta simplificación,
llamada factor(), que se discutirá a continuación más adelante.
Otro problema de simplify() es que puede ser innecesariamente lento, ya que intenta muchos
tipos de simplificaciones antes de elegir el mejor. Si se sabe exactamente qué tipo de simplificación
se está buscando, es mejor aplicar las funciones de simplificación específicas que aplican esas
simplificaciones.

 159 
4.2.2.2 Función expand()
expand() es una de las funciones de simplificación más comunes en sympy. Aunque tiene
muchos alcances, por ahora, solo se considerará su función en la expansión de expresiones
polinomiales. Por ejemplo:

Figura 4.38 Utilizando expand() Figura 4.39 Resultado al ejecutar el programa


expand() no puede sonar como una función de simplificación. Después de todo, por su propio
nombre, hace las expresiones más grandes, no más pequeñas. Normalmente este es el caso, pero a
menudo una expresión se vuelve más pequeña al llamar a expand() en ella debido a la cancelación.
Esta situación se muestra en el programa de la figura 4.40. El resultado de la ejecución del mismo
se tiene en la figura 4.41.

Figura 4.40 Utilizando expand() para simplificar Figura 4.41 Resultado al ejecutar el programa

4.2.2.3 Función factor()


factor() toma un polinomio y lo factoriza en factores irreducibles sobre los números racionales.
Para polinomios, factor() es lo contrario de expand(). factor() utiliza un algoritmo de factorización
multivariante completo sobre los números racionales, lo que significa que cada uno de los factores
devueltos por factor() se garantiza que es irreducible.
En el programa de la figura 4.42 utiliza la función factor(). El resultado de la ejecución del
mismo se muestra en la figura 4.43.

 160 
Figura 4.42 Utilizando factor() Figura 4.43 Resultado al ejecutar el programa
Si se quieren conocer los factores mismos del polinomio, factor_list() devuelve una salida más
estructurada.

Figura 4.44 Utilizando factor_list() Figura 4.45 Resultado al ejecutar el programa


La entrada a factor() y expand() no necesita ser polinomios en sentido estricto. Estas funciones
inteligentemente factorizan o expanden cualquier tipo de expresión, aunque tenga en cuenta que
los factores no pueden ser irreductibles si la entrada ya no es un polinomio sobre los racionales.
Esto se muestra en el programa de la figura 4.46. El resultado de la ejecución del mismo se muestra
en la figura 4.47.

Figura 4.46 Utilizando factor() Figura 4.47 Resultado al ejecutar el


programa

 161 
4.2.2.4 Función collect()
collect() junta las potencias comunes de un término en una expresión. Además es
particularmente útil en conjunción con el método .coeff(). expr.coeff (x, n) da el coeficiente de x**n
en expr. El uso de .coeff() y del método expr.coeff (x, n) se muestran en el programa de la figura
4.48 y su resultado al ejecutarlo en la figura 4.49.

Figura 4.48 Utilizando collect() y el método Figura 4.49 Resultado al ejecutar el programa
expr.coeff (x, n)

4.2.2.5 Función cancel()


cancel() tomará cualquier función racional y la pondrá en la forma canónica estándar, p/q, donde
p y q son polinomios expandidos sin factores comunes, y los coeficientes principales de p y q no
tienen denominadores (es decir, son números enteros). En otras palabras, cancela factores comunes.
Ejemplos del uso del cancel() se muestran en el programa de la figura 4.50. El resultado de su
ejecución se tiene en la figura 4.51.

Figura 4.50 Utilizando cancel()

 162 
Figura 4.51 Resultado al ejecutar el programa

4.2.2.6 Función apart()


apart() realiza una descomposición en fracciones parciales sobre una función racional. En la
figura 4.52 se tiene un programa que utiliza dicha función. El resultado de ejecutarlo se muestra en
la figura 4.53.

Figura 4.52 Utilizando apart()

Figura 4.53 Resultado al ejecutar el programa

4.2.3 Simplificaciones trigonométricas


sympy sigue las convenciones de nomenclatura de Python para las funciones trigonométricas
inversas, que es añadir un a al frente del nombre de la función. Por ejemplo, el coseno inverso, o
arco coseno, se llama acos().

4.2.3.1 Función trigsimp()


Para simplificar expresiones utilizando identidades trigonométricas, se utiliza trigsimp(), que
también trabaja con funciones trigonométricas hiperbólicas. Ejemplos de su aplicación se muestran
en el programa de la 4.54. Mientras que el resultado de su ejecución en la figura 4.55.

 163 
Figura 4.54 Utilizando trigsimp() Figura 4.55 Resultado al ejecutar el
programa

4.2.3.2 Función expand_trig()


Para expandir funciones trigonométricas, es decir, aplicar las identidades de suma o doble
ángulo, se utiliza expand_trig().
Debido a que expand_trig() tiende a hacer que las expresiones trigonométricas sean más
grandes, y trigsimp() tiende a hacerlas más pequeñas, estas identidades pueden aplicarse en sentido
inverso. En la figura 4.56 se tiene un programa que utiliza dichas funciones. La ejecución del
mismo se muestra en la figura 4.57.

Figura 4.56 Utilizando expand_trig() Figura 4.57 Resultado al ejecutar el programa


También es posible utilizar la función expand() para expandir funciones trigonométricas, lo que
se requiere es utilizarla de la siguiente forma expand(expr, trig=True).
En el programa de la figura 4.58 se utilizan ambas funciones para expandir la expresión
trigonométrica cos(3x), el resultado de su ejecución se tienen en la figura 5.49 y se observa que el
resultado es exactamente el mismo.

 164 
Figura 4.58 Utilizando expand() y expand_trig() Figura 4.59 Resultado al ejecutar el programa

4.3 Cálculo

Como buen paquete de cálculo simbólico que es, sympy ofrece numerosas posibilidades para
realizar tareas comunes del cálculo infinitesimal, como son calcular límites, derivadas, series e
integrales simbólicas. Por ejemplo, mientras que con el paquete scipy se puede calcular, utilizando
diferencias centradas, la derivada de una función en un punto utilizando la función
scipy.misc.derivative, con sympy se puede calcular la derivada simbólica de la función.

4.3.1 Derivación
Para calcular la derivada simbólica en sympy (esto es: la función derivada) se usa la función
diff(), cuya sintaxis es: diff(func, var); o el método expr.diff(var) de una expresión.
En la figura 4.60 se muestra un programa en el cual se muestran la función diff() y el método
expr.diff() para obtener la misma derivada simbólica de la expresión cos(x). El resultado de su
ejecución se tiene en la figura 4.61 y como se observa es el mismo en ambos casos.

Figura 4.60 Utilizando diff() y el método .diff() Figura 4.61 Resultado al ejecutar el programa
Con diff() se pueden calcular múltiples derivadas a la vez. Para calcular múltiples derivadas, se
pasa la variable tantas veces como se desee diferenciar, o se pasa un número después de la variable.
Por ejemplo, el programa de la figura 4.62 se tienen dos formas de encontrar la tercera derivada de

 165 
x4. El resultado de la ejecución de dicho programa se muestra en la figura 4.62 y como se observa
es el mismo en ambos casos.

Figura 4.62 Utilizando diff() para calcular Figura 4.63 Resultado al ejecutar el programa
derivadas múltiples
También se pueden calcular derivadas con respecto a muchas variables a la vez (derivadas
parciales). Simplemente se pasa cada derivado en orden, usando la misma sintaxis que para las
derivadas de una sola variable.
En el programa de la figura 4.64 se tienen tres maneras diferentes para calcular (∂7/∂x∂y2∂z4)exyz.
El resultado al ejecutarlo se muestra en la figura 4.65 y como se observa es el mismo en los tres
casos.

Figura 4.64 Utilizando diff() para Figura 4.65 Resultado al ejecutar el programa
calcular derivadas parciales
Para crear una derivada sin evaluar, se utiliza la clase Derivada. Tiene la misma sintaxis que
diff().Para evaluar un derivado no evaluado, se utiliza el método .doit(). Esto se muestra en el
programa de la figura 4.66 y la ejecución del mismo en la figura 4.67.

 166 
Figura 4.66 Mostrando y calculando Figura 4.67 Resultado al ejecutar el programa
derivadas sin evaluar
Estos objetos no evaluados son útiles para retrasar la evaluación de la derivada o para fines de
impresión. También se utilizan cuando sympy no sabe cómo calcular la derivada de una expresión,
por ejemplo, si contiene una función indefinida.
También, utilizando sustitución tal como se vio, se puede calcular la derivada en un punto o
dejar la derivada sin efectuar utilizando el argumento evaluate. Esto se muestra en el programa de
la figura 4.68. El resultado de su ejecución se observa en la figura 4.69.

Figura 4.68 Mostrando derivada sin evaluar y Figura 4.69 Resultado al ejecutar el programa
calculando la derivada en un punto

4.3.2 Integración
Para calcular integrales definidas e indefinidas con sympy se utiliza la función integrate(). Esta
utiliza el algoritmo de Risch-Norman extendido más algunas reglas heurísticas y búsqueda de
patrones.
Para calcular una integral indefinida, es decir, una antiderivada o primitiva, simplemente se pasa
la variable después de la expresión. Varios ejemplos se muestran en el programa de la figura 4.70.
Los resultados al ejecutarlo se tienen en la figura 4.71.

 167 
Figura 4.70 Utilizando integrate() en integrales Figura 4.71 Resultado al ejecutar el programa
indefinidas
Hay que tener en cuenta que sympy no incluye la constante de integración. Si se deseas, uno
mismo la puede añadir o reformular el problema como una ecuación diferencial y usar dsolve(()
para resolverlo, lo cual agrega la constante.
Para calcular una integral definida, pasar el argumento (variable de integración, límite inferior,
límite superior). Por ejemplo, calcular:

∫ 𝑒 −𝑥 𝑑𝑥
0

El programa de la figura 4.72 calcula dicha integral. Su resultado al ejecutarlo se muestra en la


figura 4.73.

Figura 4.72 Utilizando integrate() en integrales Figura 4.73 Resultado al ejecutar el programa
definidas
Como con las integrales indefinidas, puede pasar múltiples listas de límites para realizar una
integral múltiple. Por ejemplo, calcular
∞ ∞
2 −𝑦 2
∫ ∫ 𝑒 −𝑥 𝑑𝑥𝑑𝑦
−∞ −∞

El programa de la figura 4.74 calcula dicha integral múltiple. El resultado se observa en la figura
4.75.

 168 
Figura 4.74 Utilizando integrate() en integrales múltiples Figura 4.75 Resultado al ejecutar el
programa
Si la función integrate() es incapaz de calcular una integral, devuelve un objeto integral no
evaluado. Esto se muestra en el programa de la figura 4.76. El resultado al ejecutarlo se observa en
la figura 4.77.

Figura 4.76 Integral no evaluada Figura 4.77 Resultado al ejecutar el programa


Al igual que con Derivative, puede crear una integral no evaluada utilizando Integral. Para
evaluar posteriormente esta integral, se utiliza el método doit(). Esto se muestra en el programa de
la figura 4.78, cuyo resultado al ejecutarlo se muestra en la figura 4.79.

Figura 4.78 Utilizando doit() para evaluar una integral Figura 4.79 Resultado al ejecutar el programa

4.3.3 Límites
Para calcular límites simbólicos con sympy se utiliza la función limit(). Se puede calcular el
límite de casi cualquier expresión, con una o varias variables y por los dos lados.
sympy utiliza el algoritmo de Gruntz para calcular límites y requiere evaluar la serie de las
funciones, por lo que los límites no pueden involucrar funciones definidas por el usuario.
La sintaxis para calcular:

 169 
lim 𝑓(𝑥)
𝑥→𝑥0

es limit(f(x), x, x0).
Un ejemplo del uso de dicha función se tiene en el programa de la figura 4.80. El resultado de
su ejecución se muestra en la figura 4.81.

Figura 4.80 Utilizando limit() Figura 4.81 Resultado al ejecutar el programa


limit() se debe utilizar en lugar de subs() siempre que el punto de evaluación es una
singularidad. A pesar de que sympy tiene objetos para representar ∞, usarlos para la evaluación no
es confiable porque no siguen un seguimiento de cosas como la tasa de crecimiento.
Además, cosas como ∞∞, y ∞/∞ devuelven nan (not-a-number, no es un número). En la figura
4.82 se tiene un programa que utiliza subs() y limit() para obtener el límite de una singularidad. El
resultado al ejecutarlo se muestra en la figura 4.83.

Figura 4.82 Utilizando limit() y subs() en una Figura 4.83 Resultado al ejecutar el programa
singularidad
Como Derivate e Integral, limit() tiene una homologo no valorado, Limit. Para evaluarlo, se
utiliza el método doit().
En el programa de la figura 4.84 se muestra el uso de doit() en limites. EL resultado al ejecutarlo
se observa en la figura 4.85.

 170 
Figura 4.84 Utilizando doit() Figura 4.85 Resultado al ejecutar el programa
Para evaluar un límite en un solo lado, utilizar '+' o '' como un tercer argumento de limit(). Por
1 1
ejemplo, calcular: lim+ 𝑥 y lim− 𝑥 .
𝑥→0 𝑥→0

Dichos límites son calculados por el programa de la figura 4.86. El resultado al ejecutar dicho
programa se muestra en la figura 4.87.

Figura 4.86 Utilizando doit() Figura 4.87 Resultado al ejecutar el programa

4.4 Resolución de ecuaciones


Las ecuaciones simbólicas en sympy no están representadas por = o ==, sino por Eq(ecuación,
igual_a). En el programa de la figura 4.88 se muestra el uso de Eq(). El resultado de su ejecución
se tiene en la figura 4.89.

Figura 4.88 Utilizando Eq() Figura 4.89 Resultado al ejecutar el programa

 171 
En el programa de la figura 4.88 se utiliza una nueva instrucción para impresión: pprint() para
dar un formato diferente a la impresión de salida. Se le conoce como pretty printer (impresión
bonita) de ASCII. Si el terminal no admite Unicode, la impresora ASCII se utiliza de forma
predeterminada. De lo contrario, se debe pasar el argumento use_unicode = False. En el programa
de la figura 4.90 se muestran tres diferentes maneras de presentar una salida de una integral. El
resultado al ejecutar el programa de observa en la figura 4.91.

Figura 4.90 Utilizando pprint() Figura 4.91 Resultado al ejecutar el programa


Regresando a la resolución de ecuaciones, hay una manera aún más fácil de utilizar Eq(). En
sympy, cualquier expresión en Eq() se asume automáticamente que es igual a 0 por las funciones
de resolución. Puesto que a = b si y sólo si a  b = 0, esto significa que en lugar de usar x == y, se
puede utilizar x  y. Esto se muestra en el programa de la figura 4.92 y el resultado de la ejecución
del mismo en la figura 4.93.

Figura 4.92 Definiendo ecuaciones Figura 4.93 Resultado al ejecutar el programa


Esto es particularmente útil si la ecuación que desea resolver ya es igual a 0. En lugar de escribir
solveset(Eq(expr, 0), x), puede usar solveset(expr, x).
La función principal para resolver ecuaciones algebraicas es solveset(). La sintaxis para
solveset() es solveset(ecuación, variable = None, domain = S.Complexes), donde las ecuaciones
pueden estar en forma de instancias de Eq() o expresiones que se supone que son iguales a cero.

 172 
Hay que tener en cuenta que hay otra función llamada solve() que también se puede utilizar para
resolver ecuaciones. La sintaxis es solve(ecuaciones, variables). Sin embargo, se recomienda usar
solveset() en su lugar.
Al resolver una única ecuación, la salida de solveset() es un FiniteSet o un Interval o ImageSet
de las soluciones. En el programa de la figura 4.94 se muestran estos tres tipos de salidas impresos
en forma normal y con pprint(). El resultado de la ejecución del mismo se tiene en la figura 4.95.

Figura 4.94 Resolución de ecuaciones Figura 4.95 Resultado al ejecutar el programa


Si no hay soluciones, se devuelve un EmptySet y si no es capaz de encontrar soluciones, se
devuelve un ConditionSet. Esto se muestra en el programa de la figura 4.96 y el resultado de su
ejecución en la figura 4.97.

Figura 4.96 Resultados sin soluciones Figura 4.97 Resultado al ejecutar el programa
En el módulo de solveset, el sistema lineal de ecuaciones se resuelve usando linsolve. En el
futuro se podría usar linsolve directamente de solveset. En la figura 4.98 se muestran ejemplos de
la sintaxis de linsolve en sus tres casos:
• Forma de lista de ecuaciones
• Forma de Matriz Aumentada
• Forma A * x = b
El resultado de la ejecución de dicho programa se muestra en la figura 4.99.

 173 
Figura 4.98 Utilizando linsolve() Figura 4.99 Resultado al ejecutar el
programa
El orden de la solución corresponde al orden de los símbolos dados.

4.5 Álgebra Lineal

El Álgebra lineal es una rama de las matemáticas que es sumamente utilizada en el estudio de
una gran variedad de ciencias, como sería ingeniería, finanzas, investigación operativa, entre otras.
Es una extensión del álgebra hacia un mayor número de dimensiones; en lugar de trabajar con
incógnitas a nivel de escalares se comenzará a trabajar con matrices y vectores.

4.5.1 Escalares, vectores y matrices


El estudio del Álgebra lineal implica trabajar con varios objetos matemáticos, como ser:
 Escalares: Un escalar es un solo número, en contraste con la mayoría de los otros objetos
estudiados en Álgebra lineal, que son generalmente una colección de múltiples números.
 Vectores: Un vector es una serie de números. Los números tienen un orden preestablecido, y
se pueden identificar cada número individual por su índice en ese orden. Se puede pensar en
los vectores como la identificación de puntos en el espacio, con cada elemento que da la
coordenada a lo largo de un eje diferente. Existen dos tipos de vectores, los vectores de fila
y los vectores de columna. Se pueden representarlos de la siguiente manera, f es un vector de
fila y c es un vector de columna:
−1
𝑓 = [1 0 −1] 𝑐=[ 0 ]
1

 174 
 Matrices: Una matriz es un arreglo bidimensional de números (llamados entradas de la
matriz) ordenados en filas (o renglones) y columnas, donde una fila es cada una de las líneas
horizontales de la matriz y una columna es cada una de las líneas verticales. En una matriz
cada elemento puede ser identificado utilizando dos índices, uno para la fila y otro para la
columna en que se encuentra. Se pueden representar de la siguiente manera, A es una matriz
de 3×2.
0 1
𝐴 = [−1 2]
−2 3
Sobre estos objetos se pueden realizar las operaciones matemáticas básicas, como ser adición,
multiplicación, sustracción y división, es decir que se va a poder sumar vectores con matrices,
multiplicar escalares a vectores y demás.

4.5.2 Creando vectores y matrices


Para crear una matriz o un arreglo en sympy, se utiliza el objeto Matrix. Se construye una matriz
proporcionando una lista de vectores de fila que forman la matriz, para un vector se proporciona
solamente una lista en forma de fila o en forma de columna. Por ejemplo, para construir la matriz
y los vectores fila y columna
1 −1 4
𝑀 = [3 4 ] , 𝑉1 = [1 2 3], 𝑉2 = [5]
0 2 6
se puede utilizar un programa como el de la figura 4.100. El resultado de su ejecución se muestra
en la figura 4.101.

Figura 4.100 Definiendo matrices y vectores Figura 4.101 Resultado al ejecutar el


programa

 175 
Este es el caso se dio valores fijos para la matriz y los vectores, pero se puede solicitar al usuario
que él sea el que los introduzca haciendo un programa similar al de la figura 4.102. Una posible
ejecución del mismo se muestra en la figura 4.103.

Figura 4.102 Introduciendo matrices Figura 4.103 Resultado al ejecutar el


programa
Además de crear una matriz a partir de una lista de listas y/o matrices de tamaño adecuado,
sympy también admite métodos más avanzados de creación de matriz incluyendo una única lista
de valores y entradas de dimensión. Esto último se muestra en el programa de la figura 4.104.
Mientras que el resultado de su ejecución se observa en la figura 4.105.

Figura 4.104 Definiendo matrices Figura 4.105 Resultado al ejecutar el programa


Una cosa importante a tener en cuenta sobre las matrices sympy es que, a diferencia de cualquier
otro objeto en sympy, son mutables. Esto significa que se pueden modificar en su lugar, como se
verá a más adelante. La desventaja de esto es que Matrix() no se puede utilizar en lugares que
requieren inmutabilidad, como dentro de otras expresiones sympy o como claves para los
diccionarios. Si se necesita una versión inmutable de Matrix(), se utiliza ImmutableMatrix().
También cabe señalar que las matrices y vectores se manipulan como cualquier otro objeto en
sympy o Python.
Algo interesante (y útil), es la capacidad de sympy para utilizar una función de 2 variables (o
lambda) para crear una matriz. Aquí creamos una función de indicador que es 1 en la diagonal y

 176 
luego la usamos para hacer la matriz de identidad, tal como lo muestra el programa de la figura
4.106. El resultado de su ejecución se observa en la figura 4.107.

Figura 4.106 Utilizando una función para definir una Figura 4.107 Resultado al ejecutar el programa
matriz
Hay también varios constructores especiales para la construcción rápida de la matriz: eye() es
la matriz de la identidad, zeros() y ones() para las matrices cuyas entradas son todos ceros o unos,
respectivamente. Estos constructores se pueden utilizar tanto para vectores, como para matrices de
dimensión m×m o m×n. Además existe el constructor diag() para poner en las matrices elementos
a lo largo de la diagonal. El uso de estos constructores se muestra en el programa de la figura 4.108.
El resultado al ejecutarlo se observa en la figura 4.109.

Figura 4.108 Constructores para matrices Figura 4.109 Resultado al ejecutar el programa
Para entender un poco más el caso de las matrices diagonales, es importante señalar que los
argumentos para diag() pueden ser números o matrices. Un número se interpreta como una matriz

 177 
1×1. Las matrices se apilan en diagonal. Los elementos restantes se llenan con ceros. En el
programa de la figura 4.110 se muestra más a detalle el uso de diag(). El resultado al ejecutar el
programa se observa en la figura 4.111.

Figura 4.110 Utilizando diag() Figura 4.111 Resultado al ejecutar el programa


A diferencia de un array en numy, a una matriz de sympy se le pueden incluir también símbolos.
Esto se muestra claramente en el programa de la figura 4.112. El resultado al ejecutarlo se tiene en
la figura 4.113.

Figura 4.112 Utilizando símbolos en matrices Figura 4.113 Resultado al ejecutar el programa

4.5.3 Manipulación de arreglos y matrices


Al aprender a trabajar con matrices, se va a elegir dónde las entradas son fácilmente
identificables. Una cosa útil a saber es que mientras que las matrices son bidimensionales, el
almacenamiento de las mismas no lo es y así que es permitido, aunque se debe tener cuidado, para
tener acceso a las entradas como si fueran una lista unidimensional. Esto se puede observar en el
programa de la figura 4.114, mientras que el resultado de su ejecución se muestra en la figura 4.115.

 178 
Figura 4.114 Acceso a entradas individuales Figura 4.115 Resultado al ejecutar el programa
El acceso de entrada más estándar es un par de índices que siempre devolverá el valor en la fila
y columna correspondientes de la matriz. Esto se puede ver en el programa de la figura 4.116. El
resultado de su ejecución se muestra en la figura 4.117.

Figura 4.116 Acceso a entradas individuales Figura 4.117 Resultado al ejecutar el programa

4.5.3.1 Método shape()


Para obtener la dimensión de una matriz, se utiliza el método shape(), tal como se muestra en el
programa de la figura 4.118. El resultado de su ejecución se observa en la figura 4.119.

Figura 4.118 Utilizando el método shape Figura 4.119 Resultado al ejecutar el programa

 179 
4.5.3.2 Acceso a filas y columnas individuales
Para obtener una fila o columna individual de una matriz, se utilizan métodos row y col
respectivamente. Por ejemplo, M.row (0) devolverá la primera fila. M.col (-1) devolverá la última
columna. Esto se muestra en el programa de la figura 4.120, mientras que el resultado de su
ejecución se observa en la figura 4.121.

Figura 4.120 Acceso a filas o columnas Figura 4.121 Resultado al ejecutar el programa

4.5.3.3 Eliminar e insertar filas y columnas


Para eliminar filas o columnas, se utilizan los métodos row_del o col_del. Estos métodos
modificarán la matriz, ya que, como se mencionó anteriormente, en sympy son objetos mutables.
En el programa de la figura 4.122 a la matriz M primeramente se le elimina la columna 0, y a la
matriz resultante se le elimina la fila 1. El resultado de su ejecución se muestra en la figura 4.123.

Figura 4.122 Eliminando filas o columnas Figura 4.123 Resultado al ejecutar el programa
Para insertar filas o columnas, use utilizan los métodos row_insert o col_insert respectivamente.
A la matriz M del programa de la figura 4.124 primeramente se le inserta la fila 1, posteriormente
a la matriz resultante la columna 0. El resultado al ejecutarlo se tiene en la figura 4.125.

 180 
Figura 4.124 Insertando filas o columnas Figura 4.125 Resultado al ejecutar el programa

4.5.3.4 Operaciones con matrices y vectores


Las operaciones aritméticas como la suma, resta y multiplicación de matrices se realizan
simplemente usando +,  y *. Para encontrar la inversa de una matriz, basta con elevarla a la
potencia -1. Esto se realiza con **, que también se utiliza para multiplicar una matriz por si misma
las veces que se indiquen. Así mismo se puede multiplicar por un escalar. Estas operaciones se
realizan en el programa de la figura 4.126. El resultado al ejecutarlo se ve en la figura 4.127.

Figura 4.126 Operaciones con matrices Figura 4.127 Resultado al ejecutar el programa

 181 
Para obtener la transpuesta de una matriz se utiliza el método T. Si se quiere calcular el
determinante de una matriz se utiliza el método det. Estas operaciones se realizan en el programa
de la figura 4.128. El resultado al ejecutarlo se observa en la figura 4.129.

Figura 4.128 Más operaciones con matrices Figura 4.129 Resultado al ejecutar el programa
Además sympy tiene algunas operaciones útiles sobre vectores, como el producto cruz, para lo
cual se utiliza el método cross. También cuenta con la multiplicación de vectores, para lo cual se
utiliza en método dot. El uso de estos métodos se muestra en el programa de la figura 4.130. El
resultado de su ejecución se observa en la figura 4.131.

Figura 4.130 Operaciones con vectores Figura 4.131 Resultado al ejecutar el programa

4.6 Ecuaciones diferenciales

sympy es capaz de resolver (algunas) ecuaciones diferenciales ordinarias (EDO).


Para resolver EDO, se utiliza la función dsolve(). Primero, se crea una función indefinida
pasando cls=function a la función symbols(). Al hacer esto f y g son ahora funciones indefinidas.

 182 
Se puede llamar f(x), y representará una función desconocida. Esto se muestra en el programa
de la figura 4.132 y el resultado de su ejecución se tiene en la figura 4.133.

Figura 4.132 Definiendo una función indefinida Figura 4.133 Resultado al ejecutar el programa
Al hacer esto las derivadas de f(x) no se evalúan, tal como se ve en el programa de la figura
4.134. El resultado de su ejecución se observa en la figura 4.135.

Figura 4.134 Derivadas sin evaluar Figura 4.135 Resultado al ejecutar el programa
Para representar la ecuación diferencial f ''(x)  2f '(x) + f (x) = sin(x) se escribiría como se
muestra en el programa de la figura 4.136. El resultado de su ejecución se ve en la figura 4.137.

Figura 4.136 Representando una EDO Figura 4.137 Resultado al ejecutar el


programa
Para resolver la ecuación diferencial ordinaria, se para como argumento a la función dsolve().
Tal como se ve en el programa de la figura 4.138. El resultado al ejecutarlo se muestra en la figura
4.138.

 183 
Figura 4.138 Resolviendo una EDO Figura 4.139 Resultado al
ejecutar el programa
Las constantes arbitrarias en las soluciones de dsolve() son símbolos de la forma C1, C2, C3, y
así sucesivamente.
Si dsolve() devuelve una instancia de la ecuación o simplemente no muestra el resultado se
debe, a que en general, las soluciones a las ecuaciones diferenciales no pueden ser resueltas
explícitamente para dicha función. En el caso del programa de la figura 4.140 precisamente se tiene
una EDO que no puede ser resuelta y al ejecutar el programa este no muestra el resultado (figura
4.141) ya que ha quedado ciclado y se tiene que oprimir <crtl>+<c> o hacer clic en el botón rojo
para terminar su ejecución.

Figura 4.140 EDO que no puede ser resuelta Figura 4.141 Resultado al ejecutar el
programa
Se pueden usar argumentos en las keywords para ayudar a encontrar el mejor sistema de
resolución posible. Por ejemplo, si a priori conoces que estás tratando con ecuaciones separables,
puedes usar la palabra clave (keyword) hint=’separable’ para forzar a dsolve() a que resuelva la
EDO como una ecuación separable. El programa de la figura 4.142 utiliza dicha keyword y la
ejecución del mismo se muestra en la figura 4.143.

 184 
Figura 4.142 Utilizando la keyword hint=’separable’

Figura 4.143 Resultado al ejecutar el programa


hint=best forza a dsolve() a que resuelva de la mejor manera la EDO, esto puede ocasionar que
se tarde más en resolverla. El programa de la figura 4.144 utiliza dicha keyword y la ejecución del
mismo se muestra en la figura 4.145.

Figura 4.144 Utilizando la keyword hint=’best’

 185 
Figura 4.145 Resultado al ejecutar el programa

4.7 Actividades a realizar

Codificar y ejecutar en Python los programas para los problemas indicados en cada caso, además
de seguir las indicaciones y/o restricciones si las hubiera. En cada problema se muestran una o
varias figuras con posibles resultados de salida al ejecutar el programa. Todos los problemas deben
ser resueltos utilizando funciones.

a) Convertir una expresión valida de texto a una expresión de sympy, la cual debe de contener
solamente variables x e y. Las mismas serán modificadas a variables a y b respectivamente. La
expresión no debe estar evaluada, es decir, se debe mostrar tal y como se capturó, por ejemplo
si se escribe la expresión 3*x + 2*x - 5*y - 6*y se debe mostrar como 2*a + 3*a - 6*b - 5*b, no
5*a – 11b. Ayuda: utilizar el método .replace de cadenas y el parámetro evaluate=False de la
función adecuada para convertir cadenas a expresiones sympy. Un posible resultado al ejecutar
el programa se muestra en la figura 4.146.

 186 
Figura 4.146 Posible resultado al ejecutar el programa
b) Modificar el programa anterior para que además de convertir la expresión la evalué, tal como se
muestra en el resultado al ejecutar el programa mostrado en la figura 4.147.

Figura 4.147 Posible resultado al ejecutar el programa


c) Modificar el programa anterior para convertirlo en una calculadora algebraica, al cual se le
ingrese de una expresión y según sea el caso simplificarla con la función simplify(); expandirla
con la función expand(); factorizarla de polinomios con la función factor(), obtener sus
potencias comunes de polinomios con collect(); cancelar factores comunes con la función
cancel() o descomponerla en fracciones parciales con la función apart(). Para comprobar su
funcionalidad utilizar las expresiones que vienen como ejemplo en cada caso en el apartado
correspondiente. Recordar que ahora en vez de x e y las variables resultantes son con a y b.
Utilizar una función para cada opción. Las opciones deben estar en forma de menú. El programa
debe de regresar al menú después de haber mostrado el resultado correspondiente. Solamente se
podrá salir del programa utilizando la opción 7. Algunos posibles resultados son mostrados en
la figura 4.148.

 187 
Figura 4.148 Algunos posible resultado al ejecutar el programa

 188 
Unidad 5 Trabajando con gráficas
5.1 Introducción

En Python la biblioteca más extendida para gráficas 2D y 3D es matplotlib. Permite obtener


gráficas de muy buena calidad, con una gran capacidad de control y una curva de aprendizaje
moderada. Todos los aspectos de la figura pueden controlarse mediante código. Para más
información se puede consultar el sitio de la biblioteca: http://matplotlib.org/.
Para poder utilizar matplotlib desde un programa existe en principio dos opciones. La más
directa y tal vez más sencilla es importar el módulo pylab, tal como se muestra en la figura 5.1.

Figura 5.1 Importando matplotlib


La otra alternativa, más purista, es importar el módulo matplotlib.pyplot (como plt como
convención), de la manera que se observa en la figura 5.2.

Figura 5.2 Otra alternativa para importar matplotlib


Además es importante conocer las partes de la ventana que se abre al ejecutar un programa que
utilice matplotlib (figura 5.3) para realizar una gráfica.

Figura 5.3 Ventaja al ejecutar un programa que utiliza matplotlib


Dicha ventana consta de cuatro partes principales, las cuales se muestran en la figura 5.4. Las
mismas son:
1. Número de la figura. Número asignado a la figura.
2. Panel gráfico. Región en la cual se muestra la gráfica.

 189 
3. Barra de herramientas. Opciones para manipulación de la gráfica.
4. Coordenadas. Coordenadas de la gráfica sobre la cual está posicionado el cursor.

Número de
figura

Panel gráfico

Barra de
herramientas
Coordenadas

Figura 5.4 Partes de la ventana de ejecución de matplotlib


En la tabla 51. Se muestran las diferentes opciones de la barra de herramientas.
Tabla 5.1 Opciones de la barra de herramientas
Icono Función Descripción y/o datos adicionales
Restaurar la vista También se restaura la vista original presionando <H>, <R>
original o <Inicio>
Regresar a la vista También se regresa a la vista previa presionando <C> o la
previa flecha hacia atrás <>
Pasar a la vista También se regresa a la vista siguiente presionando <V> o
siguiente la flecha hacia adelante <>
Con el clic izquierdo se desplaza la gráfica conservando los
valores de los ejes, con el derecho se incrementan o
decrementan los valores los ejes. Se activa/desactiva
Desplazar de los ejes
presionando la techa <P>. Además presionando <2> o <3>
se bloque cualquier desplazamiento aún estado activada. Se
desbloquea presionando <1>.
Zoom al rectángulo Hace zoom en el rectángulo que se seleccione en el panel
seleccionado gráfico. Se activa/desactiva presionando <O>
Configurar las Configura la vista de la gráfica o en su caso de las
subgráficas subgráficas.
Esta función se activa/desactiva presionando <S> dos veces,
Archivar la figura
o <crtl>+<S>
Al hacer clic en la opción configurar subgráficas se muestra la ventana de la figura 5.5, en la
cual se pueden manipular sus valores para modificar la vista del panel gráfico. Los valores por
default se muestran con una línea roja, si se modifican se pueden restaurar al hacer clic en el botón
.

 190 
Figura 5.5 Ventana de la opción de configurar subgráficas
En el panel gráfico también se tienen varias opciones, las cuales son mostradas en la tabla 5.2.
Tabla 5.2 Opciones del panel gráfico
Teclas Descripción
<F> o <crtl>+<F> Activa/desactiva el modo de pantalla completa con la gráfica
<G> Activa/desactiva la cuadricula en la gráfica
Cambia el eje de las x a escala logarítmica, es necesario dar clic sobre la
<K>
gráfica
Cambia el eje de las y a escala logarítmica, es necesario dar clic sobre la
<L>
gráfica
<ctrl>+<WW> Las teclas cierra la ventana de la gráfica
Al hacer clic en la opción de archivar la figura se muestra una ventana como la de figura 5.6.
En la misma se puede guardar directamente la gráfica como archivo png por default, pero si se
quiere hacer en otro formato entonces se hace clic en el flecha hacia abajo del final del tipo de
archivo ( ) y se selecciona el formato requerido (figura 5.7). Entre los mismo se encuentra eps,
jpg, gf, pdf, ps, raw, svg y tif aparte del png.

Figura 5.6 Guardando figura como png

 191 
Figura 5.7 Guardando figura con otro formato

5.2 Funciones principales de matplotlib

El módulo Matplotlib (al igual que la mayoría de los módulos) es enorme y explicar cada una
de las funciones llevaría demasiado tiempo así que primeramente se verán las más importantes para
un usuario principiante y como se vaya necesitando se irán agregando nuevas funciones. También
su uso de ira mencionando conforme se vaya requiriendo.
Todos los programas para realizar gráficas se presentarán a manera de función para facilitar su
uso y comprensión.
Además en todos los ejemplos, aunque se importaron los módulos numpy y sympy no siempre
son necesarios sobre todo sympy, porque no se utilizan. Se incluye numpy porque dicho módulo
suele usarse con frecuencia cuando se trabaja con gráficos. sympy se pone porque así se han venido
realizando los programas desde el inicio del texto.
A continuación se mencionarán algunas de las principales funciones de matplotlib.
figure(num, figsize, dpi, facecolor, edgecolor, frameon)
Crea una nueva figura. Se puede utilizar sin argumentos. Devuelve un identificador a la figura.
Sus argumentos son:
• num = numeración de la figura, si num = None, las figuras se numeran automáticamente.
• figsize = w, h tuplas en pulgadas. Tamaño de la figura
• dpi = Resolución de la imagen en puntos por pulgada.

 192 
• facecolor = Color del rectángulo de la figura.
• edgecolor = Color del perímetro de la figura.
• frameon = Si es falso, elimina el marco de la figura.
subplot(numRows, numCols, plotNum)
Permite incluir varias gráficas en una única figura. Sus argumentos son:
• numRows = Número de filas
• numCols = Número de columnas
• plotNum = Número de gráfica
plot(x, y, linestyle, linewidth, marker)
Permite incluir varias gráficas en una única figura. Sus argumentos son:
• x = Abcisas.
• y = Ordenadas. Tanto x como y pueden ser abcisas tuplas, listas o arrays. La única condición
es que el tamaño de ambas debe ser el mismo ya que en caso contrario Python devolverá un
fallo de tipo dimensión. También se puede hacer una gráfica sin especificar la coordenada x.
• linestyle = color y tipo de dibujar la gráfica. Por ejemplo ‘k- -‘
• linewidth = ancho de línea.
• marker = Marcador.
show()
Presenta las figuras en pantalla mediante una ventana en la que se puede interactuar. Este
comando se debe añadir siempre que se necesite observar una gráfica ya que sino Python realizará
el cálculo pero no presentará la imagen. Lo usual es ponerlo al final del programa posibilitando así
la llamada a todas las figuras que se encuentren en el mismo.
legend(labels, loc)
Coloca una leyenda. Cuando se presentan varías gráficas simultáneamente este comando
identifica cada una. Puede utilizarse sin argumentos si en cada función plot (o equivalente) se ha
incluido el argumento ‘label’, que es un texto para identificar la gráfica.
plt.xlabel(‘s’, comandos_optativos)
Etiqueta el eje de abcisas de la gráfica actual.
plt.ylabel(‘s’, comandos_optativos)
Etiqueta el eje de abscisas de la gráfica actual.
plt.title(‘s’, comandos_optativos)

 193 
Etiqueta el eje de abscisas de la gráfica actual.
• s = Texto que aparecerá en el título
• comandos_optativos = En esta etiqueta englobamos todos los modificadores de la fuente etc.
plt.text(x, y, s, comandos_optativos)
Añade el texto s en las coordenadas espaciales x, y. El texto se puede modificar como otro texto
(tamaño, color, etc.). Sus argumentos son:
• x, y = Coordenadas espaciales horizontal y vertical.
• s = Texto que queremos añadir
axis()
Establece u obtiene las propiedades de los ejes. Se puede establecer el rango de coordenadas en
x e y que se quiere mostrar en el gráfico. Del mismo modo, se puede seleccionar la relación de
aspecto entre las coordenadas x e y.
• axis(), devuelve los límites de los ejes ([xmin, xmax, ymin, ymax])
• axis(v), establece los valores límites de los ejes a v = [xmin, xmax, ymin, ymax]
• axis(‘off’), elimina líneas de ejes y etiquetas
• axis(‘equal’), cambia los límites de x e y para que los incrementos de x e y tengan la misma
longitud (un círculo parece un círculo)
• axis(‘scaled’), cambia las dimensiones del plot para conseguir la misma longitud de intervalo
en x e y.
• axis(‘tight’), cambia los ejes para que se muestren todos los datos.
axhline(y, xmin, xmax)
Con esos valores de los argumentos predeterminados establecidos, la línea se ajusta al rango
representado por los correspondientes ejes. Sus argumentos son:
• y, array con los datos
• xmin = 0, valor mínimo
• xmax = 1, valor máximo
hold()
Si el parámetro es True, se puede poner más de una gráfica en el mismo panel gráfico. Si el
parámetro es False, entonces al escribir una nueva gráfica, las anteriores se borran.
grid()
Establece la malla a True (visible) o False (oculta).

 194 
savefig(ruta)
Guarda la gráfica en un archivo. Sus argumentos son:
• ruta: ruta y nombre de archivo. Los tipos de datos pueden ser .png, .eps, .pdf, .ps, .svg.
• dpi = None: resolución de la imagen en puntos por pulgada
• facecolor = ‘w’: color del rectángulo de la figura
• edgecolor = ‘w’: color del perímetro de la figura
• orientation = ‘portrait’: orientación del papel (landscape)
• format = None : (png, pdf, ps, eps y svg).
• transparent = False, si es True, creará una gráfica de fondo transparente.
close() Cierra la gráfica.

5.3 Creando una gráfica de líneas


Existen dos maneras de crear una gráfica de líneas, la primera es a partir de una lista, la segunda
es por medio de un array de numpy. Dichas formas se describirán a continuación.
La idea es crear la gráfica de la figura 5.8. Esta es una gráfica de líneas con los ocho puntos
siguientes ((0, 11), (1, 2), (2, 3), (3, 15), (4, 8), (5, 13), (6, 21), (7, 34)).

Figura 5.8 Gráfica a crear

 195 
5.3.1 Crear una gráfica a partir de una lista
El programa de la figura 5.9 creará un gráfico a partir de una lista de valores. En el eje x se
representan 8 elementos numerados del 0 al 7 y en el eje y los valores de cada uno de ellos siguiendo
el orden de la lista. El resultado al ejecutar el programa se muestra en la gráfica de la figura 5.8.
La función figure() creará una ventana con título Figure más un número entero que irá
incrementándose sucesivamente. Es posible hacer la llamada de la forma figure(num), bien para
crear la figura con la numeración que se desee, o bien, si dicha figura existe, para hacerla activa.
Como se comentó anteriormente, para crear las gráficas se hará a manera de función, por lo que
también sería posible pasarle como argumento a la función la lista de valores y ser utilizados por
plot(). Esto se muestra en el programa de la figura 5.9, y el resultado de su ejecución es nuevamente
la gráfica de la figura 5.8.

Figura 5.9 Creando una gráfica a partir de una Figura 5.10 Creando una gráfica a partir de una
lista lista como argumento de una función

5.3.2 Crear una gráfica a partir de un array de numpy


Para crear la gráfica de la figura 5.8, también se puede hacer utilizando un arreglo de numpy.
Para esto hay dos maneras de hacerlo. La primera es crear un array de numpy y utilizarlo
directamente por plot(), como lo hace el programa de la figura 5.12.

 196 
Figura 5.11 Creando una gráfica a partir de un array
La segunda es leer los datos desde un archivo, como el de la figura 5.12, y utilizarlos para la
gráfica, como lo hace el programa de la figura 5.13.

Figura 5.12 Archivo con los datos a procesar

Figura 5.13 Creando una gráfica a partir de un array con datos leídos desde un archivo

 197 
5.4 Activar y desactivar el modo interactivo de dibujo

A continuación, se utilizan los métodos ion() y ioff() que activan o desactivan el modo
interactivo de dibujo para añadir, o no, nuevos datos sobre el gráfico actual. Esto se muestra en el
programa de la figura 5.14. El resultado de su ejecución es la gráfica de la figura 5.15.

Figura 5.14 Utilizando modo interactivo Figura 5.15 Resultado al ejecutar el programa
Para saber si la sesión es o no interactiva, para se utiliza la función isinteractive(). La función
devolverá True o False. Si es True la sesión es interactiva, en caso contrario devolverá False.
En el caso de PyCharm la sesión siempre será no interactiva, tal como se muestra en el programa
de la figura 5.16 y el resultado de su ejecución en la figura 5.17.

Figura 5.16 Verificando modo interactivo Figura 5.17 Resultado al ejecutar el programa
Al ser una sesión no interactiva no hay necesidad de activar o desactivar el modo interactivo,
las gráficas se mostrarán siempre en la misma ventana.

 198 
5.5 Graficando funciones personalizadas

También es posible graficar funciones personalizadas, por ejemplo 2x2 + 5x – 2 y 4x + 1. Esto


se muestra en el programa de la figura 5.18 y la gráfica resultante en la figura 5.19.

Figura 5.18 Graficando funciones matemáticas Figura 5.19 Resultado al ejecutar el programa
En este caso se definen las funciones a graficar y se utilizan como argumentos en plot(). La
cantidad de valores que tomará x se pueden obtener con las funciones range(), arrange() o
linspace(). Con la última función se pueden obtener mayor cantidad de puntos a graficar, por lo
que la gráfica resultante será de mayor calidad.

5.6 Añadir leyendas a las gráficas


Para añadir leyendas al gráfico se asigna al argumento label de plot() la leyenda a mostrar. Y
después, se ejecuta el método legend().
Para posición de las leyendas se utiliza la opción de leyend(loc=), las opciones son:
• upper, arriba

 199 
• lower, abajo
• center, centro
• left, izquierda y
• right, derecha
Por default la posición de la leyenda es upper left.
En el programa de la figura 5.20 se utiliza dicho método. La gráfica resultante se muestra en la
figura 5.21.

Figura 5.20 Verificando modo interactivo Figura 5.21 Resultado al ejecutar el programa

5.7 Cambiar estilos de línea, marcadores y colores de una gráfica

Para dar claridad a los gráficos pueden establecerse distintos estilos de líneas, marcadores y
colores.
Los estilos de líneas (linestyle=) más comunes son:
- línea sólida -- línea a rayas -. línea con puntos y rayas
: línea punteada None Ninguna línea
Los colores (color=) son:
b: Azul g: Verde r: Rojo c: Cián
m: Magenta y: Amarillo k: Negro w: Blanco

 200 
También se puede escribir el color de las siguientes formas: nombres (‘green’); cadenas
hexadecimales (‘#008000’); tuplas con convención RGB (0,1,0) y escala de grises (‘0.8’).
Los tipos principales de marcadores (marker=) son:
+ Cruz . Punto o Círculo * Estrellas
p Pentágonos s cuadrados x Tachados D Diamantes
h Hexágonos ^ Triángulos
En el programa de la figura 5.22 se muestra un programa en el cual se han modificado los estilos
de línea, marcadores y colores. La gráfica resultante se observa en la figura 5.23

Figura 5.22 Cambiando estilos de línea, color y marcadores

Figura 5.23 Resultado al ejecutar el programa

 201 
También, es posible cambiar las fuentes de los textos, los grosores de las líneas y otras
propiedades que modifican el aspecto de un gráfico.

5.8 Añadir rótulos a los ejes


En el programa de la figura 5.24 se crea un gráfico nuevo con el método figure() donde se
representa sólo una lista de valores y se definen los rótulos de los ejes. La gráfica resultante se
observa en la figura 4.25.

Figura 5.24 Añadiendo rótulos a los ejes

Figura 5.25 Resultado al ejecutar el programa

 202 
Se han generado dos arrays con la función arange() del módulo numpy con los siguientes
valores:
El array que se obtiene con arange(8) contiene los siguiente valores:
array([0, 1, 2, 3, 4, 5, 6, 7])
El array que se obtiene con arange(0,51,10) contiene los siguiente valores:
array([ 0, 10, 20, 30, 40, 50])
Los arrays se utilizan para definir los rótulos que se mostrarán en ambos ejes. En el eje "x" el
valor del índice es sustituido por un carácter alfabético y en el eje "y", directamente, se muestran
en la escala los valores del propio array.
Las funciones xticks() y xticks() se utilizan para agregar los rótulos a los ejes.

5.9 Trabajar con varias gráficas (subplots)


El posible tener varios ejes distintos en la misma ventana gráfica, para lo cual se utiliza la
función subplot(n, m, k), la cual divide la figura en n filas y m columnas y crea unos ejes en la
posición k (contando de izquierda a derecha y de arriba a abajo). Las comas de separación entre n,
m y k no son necesarias (a menos que alguno de los valores tenga más de un dígito). Por ejemplo,
subplot(234) sería equivalente a subplot(2, 3, 4).
El programa de la figura 5.26 muestra el uso de subpolt(), dividiendo el panel gráfico en 2 filas
y 2 culumnas y utiliza las regiones 221 y el 222 pero luego se define otro subplot de 2 filas y 1
columna pero como solamente uitliza una sola, toma todo el espacio restante. La gráfica resultante
se tiene en la figura 5.27.

Figura 5.26 Utilizando subplot()

 203 
Figura 5.27 Resultado al ejecutar el programa
En el programa de la figura 5.28 se tiene otra división del panel gráfico en 2 filas y 2 columnas
tomando una en cada caso. La gráfica que resulta se muestra en la figura 5.29.

Figura 5.28 Utilizando subplot()

Figura 5.29 Resultado al ejecutar el programa

 204 
En el programa de la figura 5.30 se muestra que en cada región se pueden hacer gráficas de
manera independiente, es más se pueden tener diferentes títulos y escalas en cada uno modificando
los argumentos correspondientes en cada región. La gráfica resultante se puede observar en la
figura 5.31.

Figura 5.30 Graficando en los subplot Figura 5.31 Resultado al ejecutar el


programa
Otra posible opción para dividir el panel gráfico es utilizar la función axes(), la cual crea unos
ejes por defecto, que equivale a hacer subplot(111). En el programa de la figura 5.32 se muestra su
uso. La gráfica resultante el ejecutarlo se muestra en la figura 5.33.

Figura 5.32 Utilizando axes() Figura 5.33 Resultado al ejecutar el programa

 205 
Los dos primeros números en el argumento de la función axes() hacen referencia a las
coordenadas de la esquina inferior izquierda, y los otros dos, a la anchura y altura, respectivamente,
de los ejes a situar. Las coordenadas están normalizadas entre 0 y 1.
axes() es muy similares a subplot(), permiten colocar gráficos en cualquier ubicación en la
figura. Así que si se quiere poner un gráfico pequeño dentro de uno más grande con los mismos
ejes se utilizaría un programa similar al de la figura 5.34. La gráfica resultante se muestra en la
figura 5.35.

Figura 5.34 Utilizando axes()

Figura 5.35 Resultado al ejecutar el programa


En el programa de la figura 5.36 se utilizan los ejes definidos en la figura 5.34, para realizar una
gráfica en cada uno de ellos. La gráfica resultante se muestra en la figura 5.37.

 206 
Figura 5.36 Utilizando axes() Figura 5.37 Resultado al ejecutar el programa
Si bien el programa de la figura 5.38 es más elaborado, permite mayor control de los elementos
de la gráfica. La gráfica resultante se muestra en la figura 5.39.

Figura 5.38 Utilizando axes() con código más Figura 5.39 Resultado al ejecutar el programa
elaborado

 207 
5.10 Activar gráficas por su número o por su nombre

Si estamos trabajando con varias gráficas a la vez para activar alguna de ella en lo individual se
puede indicar el número que aparece en su barra de título de ventana del gráfico. Cualquier acción
que se realice a continuación se hará sobre el gráfico: figure(num). El programa de la figura 5.40
muestra como se la cambiado el nombre del título de la gráfica haciendo referencia al número de
la figura. La gráfica resultante se muestra en la figura 5.41.

Figura 5.40 Activando gráficas por número Figura 5.41 Resultado al ejecutar el programa
Cuando se trabaja con varios gráficos, otra posibilidad de activar una determinada gráfica es
referirse a su nombre, el cual se les asigna en la misma función figure(). Eso se realiza en el
programa de la figura 5.42. Las gráficas resultantes se muestran en la figura 5.43.

Figura 5.42 Activando gráficas por nombre

 208 
Figura 5.43 Resultado al ejecutar el programa
En el programa de la figura 5.42 se utiliza la función scatter(), la cual usa para crear gráficas
de dispersión.

5.11 Continuar "dibujando" o reiniciar la gráfica

Se podría haber hecho que un nuevo plot() borrara la gráfica anterior, en lugar de añadirla a la
existente. La función hold() es la encargada de activar o desactivar el estado de concurrencia, esto
es, si los sucesivos dibujos se mostrarán junto a los anteriores, o bien éstos serán borrados y
sustituidos por el último. Se puede cambiar de estado invocándola sin parámetro, o bien activarlo
o desactivarlo mediante hold(True) o hold(False), respectivamente.

Figura 5.44 Realizando dos gráficas Figura 5.45 Resultado al ejecutar el programa

 209 
El programa de la figura 5.44 dibuja 2 gráficas (figura 5.45), pero no se quería presentarlas en
la misma ventana por lo que según la teoría al utilizar hold(False) solamente se mostraría la
segunda gráfica. Y efectivamente eso ocurre (figura 5.47), pero además se muestra el mensaje de
la figura 5.48.

Figura 5.46 Utilizando hold(False) Figura 5.47 Resultado al ejecutar el programa

Figura 5.48 Mensaje de función obsoleta


Este mensaje indica que hold() es obsoleto. En todo caso existe la función clf() que borra el
gráfico por completo y debe de producir el mismo resultado que hold(False). Esto se muestra en
el programa de la figura 5.49. La gráfica resultante de observa en la figura 5.50, que como se ve es
la misma que la de la figura 5.47.

Figura 5.49 Utilizando clf() Figura 5.50 Resultado al ejecutar el programa

 210 
5.13 Guardar una gráfica

Algo no menos importante es el uso de la función savefig(), que permite guardar cualquiera de
las figuras que se haya creado. Si se quiere guardar la gráfica generada por el programa de la figura
5.51 y cuyo resultado se muestra en la figura 5.52 se agrega la línea savefig() y el nombre con el
que se desee guardar, en este caso ‘grafica17.png’. Esta función también permite definir la
resolución de la imagen, el formato de salida (por defecto, matplotlib solo permite los formatos
png, eps, ps, png y svg, pero si se quiere usar otros formatos haría falta instalar otras librerías (o
bibliotecas, como PIL), la orientación de la figura, etc.

Figura 5.51 Guardando una gráfica


Nótese que en las cadenas de caracteres que conforma la etiqueta para la leyenda de la gráfica
inferior se ha usado notación Latex.

Figura 5.52 Resultado al ejecutar el programa

 211 
En la figura 5.53 se muestra el archivo de la gráfica guardada en el dispositivo indicado, y en la
figura 5.54 la gráfica resultante guardada con formato png.

Figura 5.53 Archivo de la gráfica guardada Figura 5.54 Gráfica guardada en formato png

5.13 Dibujar una gráfica de diferentes maneras

5.13.1 Gráfica de barras horizontales


La función para generar gráficas de barras horizontales es barh(). La manera en que se genera
una gráfica de este tipo se muestra en el programa de la figura 5.55 y la gráfica resultante se observa
en la figura 5.56.

Figura 5.55 Generando gráfica de barras horizontales Figura 5.56 Resultado al ejecutar el
programa
Si se requieren barras múltiples hay que modificar el programa de una forma similar al del
programa de la figura 5.57, que genera barras múltiples verticales.

 212 
5.13.2 Gráfica de múltiples barras verticales
La función para general barras verticales es bar(). Si se desean barras múltiples se tiene que
indicar el espaciado entre cada grupo de barras. La manera de hacerlo se muestra en el programa
de la figura 5.57. La gráfica resultante se observa en la figura 5.58.

Figura 5.57 Generando gráfica de múltiples barras Figura 5.58 Resultado al ejecutar el
verticales programa

5.13.3 Gráfica circular


Si se quiere realizar una gráfica circular (o de pie), la función para hacerlo es precisamente pie().
La manera para realizarla se muestra en el programa de la figura 5.59. La gráfica resultante se
observa en la figura 5.60.

Figura 5.59 Generando gráfica de pie Figura 5.60 Resultado al ejecutar el


programa

 213 
5.14 Más ejemplos de gráficas

La cantidad de tipos de gráficos diferentes que matplotlib puede generar es enorme, por lo que
es muy recomendable echarle un vistazo a la galería que aparece en la página web del proyecto
(matplotlib.org/gallery). No sólo se pueden apreciar las posibilidades de creación de gráficos sino
que además se puede ver el código con el que se generan.
A continuación se mostrarán y explicará, un poco más detallado, varias maneras de generar
gráficas más elaboradas.
Primeramente se explicará cómo el programa de la figura 5.61 genera la gráfica de la figura
5.62.

Figura 5.61 Creando una gráfica más elaborada


La función axis() muestra y/o establece las propiedades de los ejes. En concreto, el argumento
tight hace que los ejes se ajusten a los datos de la gráfica. Otras posibilidades son 'off', 'equal' o
'scaled'.
La función grid() activa o desactiva (con True o False, respectivamente) la cuadricula que puede
verse de fondo en el gráfico. Es posible especificar, no sólo dónde se sitúan las marcas de los ejes,
sino también, la etiqueta que lleva cada una.
En esta gráfica se ha hecho de forma diferente para cada eje. Con la función xticks(), que admite
una o dos listas, se señala la posición de las marcas con la primera lista, y, si existe, la cadena de
caracteres que se imprimirá en cada etiqueta con la segunda. Nótese el uso de notación Latex.

 214 
En el eje y se han determinado las marcas mediante el método set_yticks y las etiquetas con
set_yticklabels. Esta segunda opción nos permite además especificar color, tamaño de fuente o
rotación, entre otras propiedades. Además se ha añadido un nuevo objeto en el gráfico, una banda
vertical de resaltado con la función axvspan(), a la que a la que hemos modificado el color y la
transparencia con los métodos adecuados.

Figura 5.62 Resultado al ejecutar el programa


A continuación se explicará cómo el programa de la figura 5.63 general la gráfica de la figura
5.64, la cual tiene otro color de fondo.

Figura 5.63 Generando otra una gráfica

 215 
Algunas de las opciones empleadas son: el método axisbg proporciona el color de fondo de los
ejes; en este caso, el color se ha determinado a través de una tupla de valores reales entre 0 y 1 en
formato RGB (Red, Green, Blue).
La función text() sitúa una cadena de caracteres en las coordenadas determinadas por los dos
primeros argumentos. En el ejemplo, los datos con los que se ha construido la gráfica han sido
usados para determinar tales coordenadas.
Puesto que la cadena contenía acentos (en el primer texto) y notación Latex (en el segundo), se
han pasado como Unicode y raw, respectivamente. El resto de opciones son evidentes.
También se han incluido flechas para señalar objetos en el gráfico con la función arrow(), la
cual precisa de cuatro coordenadas; las dos primeras señalan el origen del vector, y las dos segundas
las coordenadas del desplazamiento (que no las coordenadas del extremo). Las demás opciones
empleadas son autoexplicativas.

Figura 5.64 Resultado al ejecutar el programa


Finalmente se explicará cómo el programa de la figura 5.65 genera la gráfica de la figura 5.66.
Como se puede ver, esta gráfica ha sido generado con la función scatter() que en lugar de dibujar
líneas, dibuja un conjunto de puntos (sin relacionar) cuyas coordenadas vienen dadas por dos listas
(en este caso, dos arrays aleatorios).
El resto de funciones establece leyendas para los ejes (con xlabel() e ylabel()), los límites que
determinan los ejes del gráfico (con xlim() e ylim()), y las marcas que se muestran en cada eje (con

 216 
xticks() e yticks()), que son definidas a través de una lista o un array. Por último, la función
minorticks_on() activa las marcas de subdivisión en ambos ejes.

Figura 5.65 Generando una última gráfica Figura 5.66 Resultado al ejecutar el programa

5.15 Dibujando gráficas 3D

Aunque la librería matplotlib fue diseñada, en principio, para trabajar con gráficas
bidimensionales también incorpora la posibilidad de realizar gráficas 3D, aunque se ha de señalar
que existen otras alternativas interesantes como MayaVi.
Para usar gráficos 3D con matplotlib primeramente se debe realizar la importación mostrada en
la figura 5.67.

Figura 5.67 Resultado al ejecutar el programa


A continuación, se utiliza la opción projection=’3d’ a la hora de crear los ejes, como se muestra
en la figura 5.68.

Figura 5.68 Resultado al ejecutar el programa


Se pueden dibujar gráficas con la función plot() vinculado a este tipo de ejes, usando tres listas
o arreglos que proporcionan las coordenadas de los puntos de la curva. Un ejemplo de generación

 217 
de una gráfica en 3D se muestra en el programa de la figura 5.69. La gráfica resultante se observa
en la figura 5.70.

Figura 5.69 Generando gráfica 3D Figura 5.70 Resultado al ejecutar el programa


Para dibujar superficies se emplea la misma técnica que en MATLAB, esto es, se necesitan crear
dos matrices de datos que generan los puntos de una cuadricula bidimensional sobre la que se
define la función a dibujar. Por ejemplo, si se quiere dibujar la gráfica de la función
𝑓(𝑥, 𝑦) = sin(2𝜋√𝑥 2 + 𝑦 2 )
en el dominio [1; 1] × [1; 1] se han de preparar los datos de la siguiente forma indicada en el
programa de la figura 5.71. La gráfica resultante se muestra en la figura 5.72.

Figura 5.71 Generando otra gráfica en 3D

 218 
Figura 5.72 Resultado al ejecutar el programa

5.15 Actividades a realizar

Codificar y ejecutar en Python los programas para los problemas indicados en cada caso, además
de seguir las indicaciones y/o restricciones si las hubiera. En cada problema se muestran una o
varias figuras con posibles resultados de salida al ejecutar el programa. Todos los problemas deben
ser resueltos utilizando funciones.

a) Una familia de curvas se compone de funciones que comparten la misma estructura y que
difieren únicamente por un parámetro constante. Por ejemplo: f(x)=sin(x)+k. La anterior es una
familia de curvas de la función seno, donde k es una constante que determina el "corrimiento"
vertical de dichas gráficas. Implementar un programa que grafique un número finito de curvas
pertenecientes a una determinada familia, como las mostradas en la figura 5.73.

Figura 5.73 Familia de curvas

 219 
b) Realizar un programa que grafique las funciones √1 − (|𝑥| − 1)2 y arccos(1 − |𝑥|) − 𝜋. El
resultado al ejecutar el programa se muestra en la figura 5.74.

Figura 5.74 Resultado al ejecutar el programa


c) Realizar un programa que grafique la función 2𝑠𝑖𝑛(4𝑥) − 𝑥2 + 10𝑥. El resultado al ejecutar el
programa se muestra en la figura 5.75.

Figura 5.75 Resultado al ejecutar el programa

d) Realizar un programa que grafique las funciones 𝑅 = √𝑥 2 + 𝑦 2 y Z = sin(R). El resultado al


ejecutar el programa se muestra en la figura 5.76. Como se observa es una gráfica en 3D.

Figura 5.76 Resultado al ejecutar el programa

 220 
e) Es posible crear gráficas con coordenadas polares utilizando matplotlib. Básicamente existen
dos maneras para realizar las gráficas:
a. Utilizando proyección polar:
ax = fig.add_subplot(111, projection="polar")
Cuyo resultado se muestra en la figura 5.77 i)
b. Utilizando la función polar()
plt.polar(theta, r)
Cuyo resultado se muestra en la figura 5.77 ii)

i) ii)
Figura 5.77 Graficando con coordenadas polares
Realizar un programa que muestre las siguientes gráficas en coordenadas polares: 1. Círculo; 2.
Cardiodie; 3. Caracol; 4. Rosa polar de 3 hojas; 5. Rosa polar de 4 hojas; 6. Lemniscata; 7.
Espiral de Arquímedes: 8. Caracol convexo y 9. Espiral circular. Dichas gráficas son mostradas
en la figura 5.78 y deben ser el resultado al solicitar cada opción.

1 2 3

 221 
4 5 6

7 8 9
Figura 5.78 Gráficas en coordenadas polares
Se debe de utilizar una función para cada opción. Las opciones deben estar en forma de menú.
El programa debe de regresar al menú después de haber mostrado la gráfica correspondiente.
Solamente se podrá salir del programa utilizando la opción 10.
f) También es posible realizar algunas manipulaciones a imágenes en matplotlib. Para ello se
utilizan las funciones imread() y imshow(). Seleccionar alguna imagen y presentar al menos
seis versiones de ella, de manera similar a la mostrada en la figura 5.79

Figura 5.79 Gráficas en coordenadas polares

 222 
Unidad 6 Colecciones de Datos
6.1 Introducción

Además de los listas, las cuales se vieron a detalle en la unidad 2, existen otros tipos de
estructuras para colección de datos, entre ellos se encuentran las tuplas, los conjuntos y los
diccionarios. Todas ellos se han utilizado en algún momento a lo largo de esta obra. A continuación
se definirán más a detalle.

6.2 Tuplas

En Python, una tupla es un conjunto ordenado e inmutable, esto es, no puede modificarse
después de su creación, de elementos del mismo o diferente tipo. Todo lo que se explicó sobre las
listas se aplica también a las tuplas, a excepción de la forma de definirla. Las tuplas se representan
escribiendo los elementos entre paréntesis y separados por comas.
En realidad no es necesario escribir los paréntesis para indicar que se trata de una tupla, basta
con escribir las comas, pero Python escribe siempre los paréntesis, tal como se muestra en el
programa de la figura 6.1. El resultado al ejecutarlo se muestra en la figura 6.2.

Figura 6.1 Definiendo tuplas Figura 6.2 Resultado al ejecutar el programa


La función len() devuelve el número de elementos de una tupla, tal como se muestra en el
programa de la figura 6.3. El resultado al ejecutarlo se observa en la figura 6.4.

Figura 6.3 Usando len() Figura 6.4 Resultado al ejecutar el programa

 223 
Una tupla puede no contener ningún elemento, es decir, ser una tupla vacía. Una tupla puede
incluir un único elemento, pero para que Python entienda que nos estamos refiriendo a una tupla
es necesario escribir al menos una coma.
El programa de la figura 6.5 se muestra primeramente una tupla vacía y luego la diferencia entre
escribir o no una coma. En el segundo caso Python interpreta la expresión como una tupla de un
único elemento y en el tercero como un número, ya que en realidad aunque se escribió tupla no lo
es, es un número. El resultado al ejecutar el programa se observa en la figura 6.6.

Figura 6.5 Diferencia en usar como o no al definir Figura 6.6 Resultado al ejecutar el programa
una tupla de un sólo elemento
Python escribe una coma al final en las tuplas de un único elemento para indicar que se trata de
un tupla, pero esa coma no indica que hay un elemento después, tal como se observa en la figura
6.7. El resultado al ejecutar el programa se muestra en la figura 6.8.

Figura 6.7 Usando len() en una tupla de un sólo Figura 6.8 Resultado al ejecutar el programa
elemento
Para verificar que se trata de una tupla y no de un número se utiliza la función type(), tal como
se muestra en el programa dela figura 6.9. El resultado al ejecutarlo se observa en la figura 6.10.

Figura 6.9 Verificando el tipo de la tupla Figura 6.10 Resultado al ejecutar el programa

 224 
Se puede hacer referencia a los elementos de las tuplas de forma individual usando corchetes,
de la misma manera que las listas. Esto se muestra en el programa de la figura 6.11 y el resultado
de su ejecución en la figura 6.12.

Figura 6.11 Referenciando elementos individuales Figura 6.12 Resultado al ejecutar el programa
Los rangos funcionan como en las listas. Al extraer un rango de una lista, se obtiene una lista
nueva; al extraerlo de una tupla, se obtiene una tupla nueva.

Figura 6.13 Utilizando rangos Figura 6.14 Resultado al ejecutar el programa


Las tuplas se pueden concatenar. Que las tuplas se puedan concatenar no significa que no sean
inmutables, porque al concatenar dos tuplas se obtiene una nueva tupla, distinta de las
concatenadas. En el programa de la figura 6.15 se concatenan dos tuplas. El resultado al ejecutarlo
se muestra en la figura 6.16.

Figura 6.15 Utilizando rangos Figura 6.16 Resultado al ejecutar el programa

 225 
6.2.1 ¿Qué no se puede hacer con las tuplas?
1. No pueden añadirse elementos a una tupla. Las tuplas no tienen los métodos append ni extend.
2. No pueden eliminarse elementos de una tupla. Las tuplas no tienen los métodos remove ni pop.
3. No pueden buscarse elementos en una tupla. Las tuplas no tienen el método index.
4. Se puede, no obstante, usar in para ver si un elemento existe en la tupla.
Entonces, ¿para qué sirven las tuplas?
Las tuplas son más rápidas que las listas. Si se está definiendo un conjunto constante de valores
y todo lo que va a hacer con él es recorrerla, es mejor utilizar una tupla en lugar de una lista.
Como las claves de un diccionario pueden ser enteros, cadenas y “algunos otros tipos”, como se
verá más adelante, las tuplas son uno de estos tipos. Las tuplas pueden utilizarse como claves en
un diccionario, pero las listas no. Realmente, es más complicado. Las claves de los diccionarios
deben ser inmutables. Las tuplas son inmutables, pero si se trata de una tupla de listas, se considera
mutable y no es seguro utilizarla como clave de diccionario. Sólo las tuplas de cadenas, números u
otras tuplas seguras pueden utilizarse como claves en un diccionario.
Las listas y las tuplas son tipos de datos similares en cuanto funcionamiento, por lo que es
factible crear una a partir de la otra. Así, si se tiene una lista con la llamada a la función
tuple(var_lista) se formatea a una tupla desde la lista pasada como parámetro. Si necesitamos una
lista a partir de una tupla, se llama a la función list(var_tupla) con la que se consigue una lista,
modificable por tanto, desde una tupla ya existente. Esto se muestra en el programa de la figura
6.17. La ejecución del programa se observa en la figura 6.18.

Figura 6.17 Utilizando rangos Figura 6.18 Resultado al ejecutar el programa

 226 
Resumiendo: las tuplas se interpretan como listas inmutables tanto en tamaño como en
contenido. Esta funcionalidad permite que sean más ligeras que las listas y mucho más eficientes,
a cambio de ser inmutables.

6.3 Conjuntos
Los conjuntos de Python son análogos a los conjuntos matemáticos. El tipo de datos que
representa a los conjuntos se llama set. En Python son una colección desordenada de valores no
repetidos. El tipo set es mutable: una vez que se ha creado un conjunto, puede ser modificado.

6.3.1 ¿Cómo crear conjuntos?


Las dos maneras principales de crear un conjunto son:
a) Utilizando un conjunto literal, entre llaves, tal como se muestra en el programa de la figura
6.19. El resultado al ejecutarlo se observa en la figura 6.20.

Figura 6.19 Definiendo conjuntos Figura 6.20 Resultado al ejecutar el


programa
Hay que observar que el conjunto no incluye elementos repetidos, y que los elementos no
quedan en el mismo orden en que fueron agregados.
b) Utilizando la función set() aplicada sobre un iterable tal como se muestra en el programa de
la figura 6.21. El resultado al ejecutarlo se observa en la figura 6.22.

Figura 6.21 Definiendo conjuntos Figura 6.22 Resultado al ejecutar el


programa

 227 
El conjunto vacío debe ser creado usando set(), ya que {} representa el diccionario vacío.
Los elementos de un conjunto deben ser inmutables. No es posible crear un conjunto de listas,
pero sí un conjunto de tuplas. Al intentar crear un conjunto de listas se mostrará un mensaje de
error. Esto se muestra en el programa de la figura 6.23. El resultado al ejecutar el programa se
observa en la figura 6.24.

Figura 6.23 Definiendo conjuntos con tuplas y Figura 6.24 Resultado al ejecutar el programa
listas
Como un conjunto no es ordenado, no tiene sentido intentar obtener un elemento usando un
índice, si se intenta se mostrará un mensaje de error. Esto se muestra en el programa de la figura
6.25. El resultado al ejecutar el programa se observa en la figura 6.26.

Figura 6.25 Obteniendo un elemento de un Figura 6.26 Resultado al ejecutar el programa


conjunto
Sin embargo, sí es posible iterar sobre un conjunto usando un ciclo for, tal como se muestra en
el programa de la figura 6.27 y el resultado de su ejecución en la figura 6.28.

Figura 6.27 Iterando sobre un conjunto Figura 6.28 Resultado al ejecutar el programa

 228 
6.3.2 Operaciones sobre conjuntos
La primera operación es la cardinalidad del conjunto, es decir, la cantidad de elementos que
contiene, la misma se obtiene con la función len(). En el programa de la figura 6.29 se observa el
uso de dicha función. El resultado al ejecutarlo se muestra en la figura 6.30.

Figura 6.29 Cardinalidad de un conjunto Figura 6.30 Resultado al ejecutar el programa


x in conjunto permite saber si el elemento x pertenece al conjunto. x not in conjunto permite
saber si x no pertenece al conjunto. Esto se muestra en el programa de la figura 631. El resultado
al ejecutarlo se observa en la figura 6.32.

Figura 6.31 Determinar si un elemento Figura 6.32 Resultado al ejecutar el programa


pertenece o no al conjunto
Para agregar elementos al conjunto se utiliza el método add. Si el elemento a agregar ya existe
en el conjunto no lo agrega. En el programa de la figura 6.33 se muestra el uso de dicho método.
El resultado al ejecutarlo se observa en la figura 6.34.

Figura 6.33 Agregando elementos al conjunto Figura 6.34 Resultado al ejecutar el programa
Para eliminar elementos de un conjunto se utiliza el método remove. Si el elemento a eliminar
no está en el conjunto, ocurre un error de llave. En el programa de la figura 6.35 se muestra el uso
de dicho método. El resultado al ejecutarlo se observa en la figura 6.36.

 229 
Figura 6.35 Eliminando elementos del conjunto Figura 6.36 Resultado al ejecutar el programa

Para la operación de unión de conjuntos se utiliza el operador | o le método unión. En la


intersección de conjuntos se utiliza el operador & o el método intersection. En cuanto a la operación
de diferencia de conjuntos se utiliza el operador  o le método difference. Para la diferencia
simétrica de conjuntos se utiliza el operador ^ o el método symmetric_difference. En el programa
de la figura 6.37 se muestra el uso de estos operadores y métodos. El resultado al ejecutarlo se
observa en la figura 6.38.

Figura 6.37 Operaciones sobre conjuntos Figura 6.38 Resultado al ejecutar el programa
Para determinar si un conjunto es un subconjunto de otro se utiliza el operador < o el método
issubset, que no diferencia entre subconjuntos y subconjuntos propio. Para determinarlo se utiliza
la combinación de operadores y métodos a.issubset(b) and a != b. Mientras que para saber si dos
conjunto son iguales se utiliza el operador <= o el operador ==. En el programa de la figura 6.39

 230 
se muestra el uso de estos operadores o métodos. El resultado al ejecutarlo se observa en la figura
6.40.

Figura 6.39 Más operaciones sobre conjuntos Figura 6.40 Resultado al ejecutar el programa
Una operación común con conjuntos es el conjunto potencia, pero este no se puede crear
utilizando el conjunto por defecto de Python. Para ello se utiliza la librería de sympy FiniteSet.
Primeramente hay que crear el conjunto con esta función y luego utilizar el método powerset.
En el programa de la figura 6.41 se muestra el uso este método. El resultado al ejecutarlo se observa
en la figura 6.42.

Figura 6.41 Conjunto potencia Figura 6.42 Resultado al ejecutar el programa


Otra operación común con conjuntos es el producto cartesiano, pero esta tampoco se puede
realizar utilizando el conjunto por defecto de Python. Para ello se utiliza nuevamente la librería de
sympy FiniteSet.
Para obtenerlo hay que crear el conjunto con esta función y luego utilizar el operador *. Si se
quiere obtener el producto cartesiano de un conjunto consigo mismo se utiliza el operador ** y la
cantidad de veces que se quiere hacer dicho producto. En el programa de la figura 6.43 se muestra
el uso estos operadores. El resultado al ejecutarlo se observa en la figura 6.44.

 231 
Figura 6.43 Producto cartesiano Figura 6.44 Resultado al ejecutar el programa
También es posible obtener los elementos del producto cartesiano utilizando un ciclo, tal como
se hace en el programa de la figura 6.45. Su resultado se muestra en la figura 6.46.

Figura 6.45 Elementos del producto cartesiano Figura 6.46 Resultado al ejecutar el programa

6.4 Diccionarios

Los diccionarios conocidos en otros lenguajes como Hashes (Perl), arreglos asociativos (PHP)
o hashmaps (Java), en Python son contenedores de pares clave-valor. A simple vista, son
simplemente arreglos o listas cuyos índices son cadenas en vez de ser números enteros.
Internamente la diferencia es mucho mayor, ya que se implementan como tablas hash en vez de
listas.
Los diccionarios no preservan el orden de los elementos: éste depende de las claves que se usen,
del orden en el que se ingresan los datos y de otros factores. Además, no se puede iterar
directamente sobre los elementos, aunque Python provee funciones para hacerlo (y también para
iterar sobre las claves).
La creación de un diccionario se realiza mediante llaves {}, separando cada registro por una
coma y la clave de su valor por dos puntos. En el programa de la figura 6.47 se crea un diccionario
 232 
con los nombres de algunos estados y sus respectivas capitales. Además de solicitar la capital de
Jalisco, ya que solo se pueden obtener valores por su clave, no por el mismo valor y mucho menos
por su posición. El resultado al ejecutarlo se muestra en la figura6.48.

Figura 6.47 Creando un diccionario Figura 6.48 Resultado al ejecutar el


programa
El primer valor se trata de la clave y el segundo del valor asociado a la clave. Como clave se
puede utilizar cualquier valor inmutable: se podrían utilizar números, cadenas, booleanos, tuplas,
pero no listas o diccionarios, dado que son mutables. Esto es así porque los diccionarios se
implementan como tablas hash, y a la hora de introducir un nuevo par clave-valor en el diccionario
se calcula el hash de la clave para después poder encontrar la entrada correspondiente rápidamente.
Si se modificara el objeto clave después de haber sido introducido en el diccionario, evidentemente,
su hash también cambiaría y no podría ser encontrado.
La diferencia principal entre los diccionarios y las listas o las tuplas es que a los valores
almacenados en un diccionario se les accede no por su índice, porque de hecho no tienen orden,
sino por su clave, utilizando de nuevo el operador corchetes [].
Al igual que en listas y tuplas también se puede utilizar el operador corchete para reasignar
valores al diccionario, tal como se muestra en el programa de la figura 6.49. El resultado al ejecutar
el programa se observa en la figura 6.50.

Figura 6.49 Modificando un elemento

Figura 6.50 Resultado al ejecutar el programa

 233 
Un diccionario puede ser expandido simplemente asignando un valor a un nuevo índice.
También se puede eliminar un valor del diccionario usando la función del(). Para eliminar todos
los elementos de un diccionario se utiliza el método clear. Un diccionario vacío se presenta con
dos llaves vacías. Todo esto se muestra en el programa de la figura 6.50. El resultado de su
ejecución se observa en la figura 6.52.

Figura 6.51 Agregando y eliminando elementos

Figura 6.52 Resultado al ejecutar el programa


Cabe mencionar que la imagen de la figura se editó para que se mostrará el resultado en varios
renglones, ya que originalmente se presentaba en un único renglón y no era posible visualizar la
imagen.
En los diccionarios no se pueden utilizar rangos, entre otras cosas, porque no son secuencias, si
no mappings (mapeados, asociaciones).
Si se intenta acceder a una clave no definida, Python lanza la excepción KeyError. Esto se
muestra en el programa de la figura 6.53. El resultado de su ejecución se observa en la figura 6.54.

Figura 6.53 Accediendo a una clave no definida Figura 6.54 Resultado al ejecutar el programa

 234 
Para evitarla, se puede comprobar fácilmente si la clave está en el diccionario usando el operador
in. Otra forma de evitar el error es utilizar el método get(). Este método recibe dos argumentos: la
clave cuyo valor se quiere obtener y el valor a retornar si la clave no está definida. Si no se
especifica el segundo parámetro, get() devuelve None. El uso del operador y del método se muestra
en el programa de la figura 6.55. Mientras que el resultado de su ejecución se observa en la figura
6.56.

Figura 6.55 Accediendo a una clave no definida Figura 6.56 Resultado al ejecutar el
programa
Al igual que las secuencias, los diccionarios también pueden ser recorridos con un ciclo for. La
diferencia es que en vez de iterar en orden sobre los elementos, el ciclo for itera sobre las claves
sin un orden preestablecido, tal como se ve en el programa de la figura 6.57. El resultado de su
ejecución se presenta en la figura 6.58.

Figura 6.57 Recorriendo a los elementos de un diccionario Figura 6.58 Resultado al ejecutar
el programa
Utilizando el método items, se recorre como una lista de tuplas (clave, valor), que se puede usar
en el for, tal como se ve en el programa de la figura 6.59. El resultado de su ejecución se presenta
en la figura 6.60.

 235 
Figura 6.59 Recorriendo los elementos de un diccionario Figura 6.60 Resultado al ejecutar
el programa
Los diccionarios soportan otras operaciones: el método copy() devuelve una copia, y el método
update() permite agregar a un diccionario las claves y valores de otro. En el programa de la figura
6.61 se muestra el uso de estos métodos El resultado de su ejecución se presenta en la figura 6.62.

Figura 6.61 Copiando y actualizando un diccionario

Figura 6.62 Resultado al ejecutar el programa


Los diccionarios no sirven solamente para almacenar cadenas. Los valores de un diccionario
pueden ser de cualquier tipo, incluidas cadenas, enteros, objetos o incluso otros diccionarios. Y en
un mismo diccionario, los valores no tienen que ser todos del mismo tipo: se pueden mezclar y
emparejar como sea necesario.
Las claves de un diccionario están más restringidas, pero pueden ser cadenas, enteros y algunos
tipos más. También se pueden mezclar y emparejar distintos tipos de claves en un diccionario.
Finalmente, al asignar un valor a una clave existente en un diccionario, simplemente se sustituye
el valor antiguo con el nuevo.
Estas últimas consideraciones se muestran en el programa de la figura 6.63. EL resultado de su
ejecución se presenta en la figura 6.64.

 236 
Figura 6.63 Diferentes tipos de claves y valores en un diccionario

Figura 6.64 Resultado al ejecutar el programa

6.5 Diagramas de Venn


El paquete matplotlib_venn proporciona varias funciones para trazar diagramas de Venn de dos
y tres conjuntos sobre matplotlib.
Las funciones se utilizan para trazar diagramas de Venn de dos y tres conjuntos con ponderación
de área.
Este paquete se utiliza en conjunto con los paquetes numpy, scipy y matplotlib, también para
definir algunos conjuntos se puede utilizar sympy.
El paquete proporciona cuatro funciones principales: venn2(), venn2_circles(), venn3() y
venn3_circles().
Las funciones venn2() y venn2_circles() aceptan como su único argumento requerido una lista
de 3 elementos (Ab, aB, AB) de tamaños de subconjunto. En el programa de la figura 6.65 se
muestra el uso de la función venn2(). El resultado al ejecutar el programa se presenta en la figura
6.66.

 237 
Figura 6.65 Utilizando la función venn2() Figura 6.66 Resultado al ejecutar el
programa
Como se observa se puede dibujar un diagrama de Venn de dos círculos con áreas de región
respectivas. En el ejemplo particular, la región correspondiente al subconjunto A y no B será tres
veces mayor en área de la región correspondiente al subconjunto A y B. Alternativamente, se puede
simplemente proporcionar una lista de dos conjuntos o Contador (es decir, multi conjunto) en su
lugar. Esto se muestra en el programa de la figura 6.67, el resultado de su ejecución se presenta en
la figura 6.68.

Figura 6.67 Utilizando la función venn2() Figura 6.68 Resultado al ejecutar el


programa
De manera similar, las funciones venn3() y venn3_circles() toman una lista de 7 elementos de
tamaños de subconjuntos (Abc, aBc, ABc, abC, AbC, aBC, ABC) y dibujan un diagrama de Venn
ponderado por área de tres círculos. Como alternativa, se puede proporcionar una lista de tres
objetos de conjunto o de contador (en lugar de contar tamaños para los 7 subconjuntos).
Las funciones venn2_circles() y venn3_circles() dibujan sólo los círculos, mientras que las
funciones venn2() y venn3() dibujan los diagramas como una colección de regiones coloreadas,
anotadas con etiquetas de texto. Además, las funciones venn2_unweighted() y
venn3_unweighted() dibujan los diagramas de Venn sin ponderación de área.

 238 
Tener en cuenta que para un diagrama de Venn de tres círculos, en general, no es posible lograr
una correspondencia exacta entre los tamaños de conjunto y las áreas de las región requeridas, sin
embargo en la mayoría de los casos la imagen seguirá proporcionando una muestra decente.
Las funciones venn2_circles() y venn3_circles() devuelven la lista de objetos
matplotlib.patch.Circle que pueden ajustarse más al gusto. Las funciones venn2() y venn3()
devuelven un objeto de la clase VennDiagram, que da acceso a las regiones constituyentes,
elementos de texto y la información sobre los centros y radios de los círculos.
Un ejemplo del uso de la función venn3_circles() se muestra en el programa de la figura 6.69.
El resultado al ejecutar el programa se presenta en le figura 6.70.

Figura 6.69 Utilizando la función venn3() Figura 6.70 Resultado al


ejecutar el programa

6.6 Actividades a realizar

Codificar y ejecutar en Python los programas para los problemas indicados en cada caso, además
de seguir las indicaciones y/o restricciones si las hubiera. En cada problema se muestran una o
varias figuras con posibles resultados de salida al ejecutar el programa. Todos los problemas deben
ser resueltos utilizando funciones.
a) Crear una tupla que contenga como elementos a los primeros 20 números naturales. Recordar
que las tuplas son inmutables, por lo que será necesario hacer algún tipo se conversión. Además
para asegurar que es una tupla utilizar la función type(). Un posible resultado al ejecutar el
programa se muestra en la figura 6.71.

Figura 6.71 Posible resultado al ejecutar el programa

 239 
b) Crea una tupla con los meses del año, pedir números al usuario, si el numero esta entre 1 y la
longitud máxima de la tupla, mostrar el contenido de esa posición sino volver a solicitar el
número. El programa termina cuando el usuario introduce un cero. Un posible resultado al
ejecutar el programa se muestra en la figura 6.72.

Figura 6.72 Posible resultado al ejecutar el programa


c) Solicitar un número por teclado y guardar en una tupla su tabla de multiplicar hasta el 10. Por
ejemplo, si pide el 5 la tupla tendrá: 5, 10, 15, 20, 25, 30, 35, 40, 45, 50. Recordar que las tuplas
son inmutables, por lo que será necesario hacer algún tipo se conversión. Además para asegurar
que es una tupla utilizar la función type(). Un posible resultado al ejecutar el programa se
muestra en la figura 6.73.

Figura 6.73 Posible resultado al ejecutar el programa


d) Solicitar números y guardarlos en una tupla, cuando el usuario introduzca un 0 dejar de insertar.
Por último, mostrar los números ordenados de menor a mayor. Recordar que las tuplas son
inmutables, por lo que será necesario hacer algún tipo se conversión. Además para asegurar que
es una tupla utilizar la función type(). Un posible resultado al ejecutar el programa se muestra
en la figura 6.74.

Figura 6.74 Posible resultado al ejecutar el programa


e) Solicitar números y guardarlos en una tupla, cuando el usuario introduzca un 0 dejar de insertar.
Por último, mostrar los números ordenados de mayor a menor. Recordar que las tuplas son
inmutables, por lo que será necesario hacer algún tipo se conversión. Además para asegurar que
es una tupla utilizar la función type(). Un posible resultado al ejecutar el programa se muestra
en la figura 6.75.

 240 
Figura 6.75 Posible resultado al ejecutar el programa
f) Crear una tupla con 30 números entre 1 y 9, solicitar al usuario un número por teclado e indicar
cuantas veces se repite dicho número. Si es un número diferente volver a solicitar el número.
Un posible resultado al ejecutar el programa se muestra en la figura 6.76.

Figura 6.76 Posible resultado al ejecutar el programa


g) Crea una tupla con al menos 20 números enteros e indicar el número con mayor valor y el que
menor tenga la tupla. Un posible resultado al ejecutar el programa se muestra en la figura 6.77.

Figura 6.77 Posible resultado al ejecutar el programa


h) Crear un diccionario donde la clave sea el nombre del usuario y el valor sea el teléfono (no es
necesario validar). Se irán solicitando contactos hasta el usuario diga que no quiere insertar más.
No se podrán introducir nombres repetidos. Un posible resultado al ejecutar el programa se
muestra en la figura 6.78.

Figura 6.78 Posible resultado al ejecutar el programa


i) Investigar más sobre los Diagramas de Venn y graficar los 5 diagramas de Venn mostrados en
la figura 6.79.

 241 
i) ii) iii)

iv) v)
Figura 6.79 Diversos diagramas de Venn
j) En el plano, una circunferencia está determinada por su centro (x, y) y por su radio r. En un
programa se puede representarla como una tupla (centro, radio), donde a su vez centro es
una tupla (x, y), por ejemplo c = ((4.0, 5.1), 2.8).
a. Escribir la función distancia(p1, p2) que calcule la distancia entre los puntos p1 y p2.
Por ejemplo, con los valores distancia((2, 2), (7, 14)) distancia((2, 5), (1, 9)) se obtendrán
los resultados mostrados en la figura 6.80.

Figura 6.80 Posible resultado al ejecutar el programa


b. Modificar el programa anterior y realizar una función, por ejemplo, se_intersectan(c1,
c2) que indique si las circunferencias c1 y c2 se intersectan. Ayuda: para determinar si
dos circunferencias se intersectan la distancia entre sus centros debe ser menor que el
radio de cualquiera de las dos circunferencias o la suma de los radios debe ser menor
que la distancia de los centros de las circunferencias.
Para este programa considerar las circunferencias mostradas en la figura 6.81.

 242 
Figura 6.81 Circunferencias consideradas para el programa
Los centros y radios de cada circunferencia son mostrados a continuación:
A = ((5.0, 4.0), 3.0)
B = ((8.0, 6.0), 2.0)
C = ((8.4, 12.7), 3.0)
D = ((8.0, 12.0), 2.0)
E = ((16.0, 7.8), 2.7)
F = ((15.5, 2.7), 2.1)
Entonces si se invoca dicha función con las circunferencias a verificar si se intersectan, por
ejemplo:
se_intersectan(A, B)
se_intersectan(C, D)
se_intersectan(E, F)
el resultado al ejecutar el programa se muestra en la figura 6.82.

Figura 6.82 Resultado al ejecutar el programa

 243 
Unidad 7 Manejo de datos por archivo
7.1 Introducción

En esta unidad se mostrará cómo manejar archivos desde un programa.


En Python, así como en cualquier otro lenguaje, los archivos se manipulan en tres pasos: primero
se abren, luego se opera sobre ellos, ya sea leyendo o escribiendo sobre los mismos, y por último
se cierran.
Los procedimientos de apertura, lectura, escritura y cierre de un archivo se detallarán a lo largo
de la unidad. También es importante señalar que solamente se trabajará con archivos de texto,
aunque se mencionarán también sobre archivos binarios.

7.2 Abriendo un archivo


En Python, para abrir un archivo se debe utilizar la función open(), que recibe como parámetros
el nombre del archivo y el modo en el que se debe abrir. De forma predeterminada (es decir, si se
omite el segundo parámetro), el archivo se abre como sólo lectura.
Es importante tener en cuenta que todas las operaciones están limitadas a la forma en la que se
abra el archivo: no se puede leer de un archivo abierto solamente para escritura, ni escribir en un
archivo abierto como solo lectura.
Existen dos formas básicas de acceder a un archivo, una es utilizarlo como un archivo de texto,
que procesaremos línea por línea; la otra es tratarlo como un archivo binario, que procesaremos
byte por byte.
El programa de la figura 7.1 muestra el uso de open(). No hay resultado al ejecutarlo porque
no se ha realizado ninguna acción sobre el archivo, solamente abrirlo.

Figura 7.1 Abriendo un archivo


Esta función intentará abrir el archivo con el nombre indicado. Si tiene éxito, devolverá una
variable que permitirá manipular el archivo de diversas maneras.

 244 
7.2.1 Modos de apertura de un archivo
Los principales modos para abrir un archivo son mostrados en la tabla 7.1.
Tabla 7.1 Modos para abrir un archivo
Modo Descripción
r Lectura
r+ Lectura/Escritura
w Sobre escritura. Si no existe archivo se creará
a Añadir. Escribe al final del archivo
b Binario
+ Permite lectura/escritura simultánea
U Salto de línea universal: win cr+lf, linux lf y mac cr
rb Lectura binaria
wb Sobre escritura binaria
r+b Lectura/Escritura binaria

En cualquiera de los modos, si el archivo no existe, es creado. Opcionalmente se puede añadir


+ al modo para que se abra en modo lectura y escritura a la vez; aunque esto no suele ser necesario
y requiere cuidado para que funcione correctamente.
Otro modificador posible es b, que sirve para trabajar con archivos binarios. Esto es necesario
en Windows para manejar correctamente archivos de imágenes, o música (toda clase de archivos
que no sean texto simple), porque el mismo sistema operativo hace diferencia entre archivos
binarios y de texto. Esto no sucede en otros sistemas operativos como Mac OS o Linux, y por tanto
en estos sistemas el modificador b no hace ninguna diferencia.
Para ejemplificar el manejo de archivos se utilizará el archivo arch_ent.txt a lo largo del tema,
el cual se muestra en la figura 7.2.

Figura 7.2 Archivo para ejemplificar acciones sobre archivos


Si se quiere abrir un archivo colgado en una web, se utiliza la biblioteca urllib, la cual debe ser
instalada, para abrirlo mediante la función urlopen(), luego, todo se hace igual para abrir el
archivo. Un ejemplo hipotético se muestra en el programa de la figura 7.3. Al ejecutar este

 245 
programa aparecería un mensaje de error (figura 7.4) pues no está instalada la librería mencionada,
además la dirección es ficticia.

Figura 7.3 Utilizando urlopne()

Figura 7.4 Resultado al ejecutar el programa

7.3 Leer datos de un archivo


Una vez abierto el archivo, se puede leer el contenido hacia una cadena con la función read(),
leer una línea con readline(), u obtener una lista conteniendo las líneas del archivo con readlines().
Los tres métodos aceptan un parámetro entero opcional que define el número máximo de bytes a
leer del archivo. Si este parámetro es negativo o simplemente se omite, read() y readlines() leerán
todo el archivo y readline() una línea completa sin importar su largo.
También se puede leer un archivo es línea por línea en un ciclo while o for, ya que el objeto
archivo es iterable.
El programa de la figura 7.5 muestra cómo es posible leer un archivo línea por línea mediante
la función readline(). El resultado al ejecutar el programa se presenta en la figura 7.6.

Figura 7.5 Leyendo un archivo línea por línea Figura 7.6 Resultado al ejecutar el programa

 246 
Esto funciona ya que cada archivo que se encuentre abierto tiene una posición asociada, que
indica el último punto que fue leído. Cada vez que se lee una línea, avanza esa posición. Es por
ello que readline() devuelve cada vez una línea distinta y no siempre la misma.
De esta manera, la variable linea irá almacenando distintas cadenas correspondientes a cada una
de las líneas del archivo.
El programa de la figura 7.7 utiliza un ciclo for y el método readlines() para leer todas las líneas
del archivo. En este caso, la variable linea tendrá una lista de cadenas con todas las líneas del
archivo. Este programa es una forma equivalente a la vista en el programa de la figura 7.5. El
resultado de su ejecución se muestra en la figura 7.8, que como se observa es el mismo que el de
la figura 7.6.

Figura 7.7 Leyendo un archivo Figura 7.8 Resultado al ejecutar el programa


NOTA: Es importante tener en cuenta que cuando se utilizan métodos como readlines(), se está
cargando en memoria el archivo completo. Siempre que una instrucción cargue un archivo
completo en memoria debe tenerse cuidado de utilizarla sólo con archivos pequeños, ya
que de otro modo podría agotarse la memoria de la computadora.

7.4 Escribir datos en un archivo

Si lo que se quiere es escribir en el archivo, se tienen los métodos write y writelines.


Contrapartes de read y readlines respectivamente, write escribe una cadena al archivo y writelines
recibe una lista de líneas para escribir.
Antes que anda, es importante señalar que si se quiere guardar en un archivo abierto de tipo w
(sobre escritura), los datos que se tengan en el archivo serán borrados por completo y reemplazados
por los datos que se hayan escrito en el. Este caso se muestra en el programa de la figura 7.9 y el
resultado al ejecutarlo se presenta en la figura 7.10. En el supuesto de que no exista el archivo, este
será creado con el nombre indicado en open().

 247 
Figura 7.9 Escribiendo en un archivo Figura 7.10 Resultado al ejecutar el programa
Lo más recomendable para escribir en un archivo es abrirlo de tipo a (añadir), el cual
precisamente añadirá lo que se pretenda escribir al final del archivo. Este caso se muestra en el
programa de la figura 7.11 y el resultado de su ejecución en la figura 7.12

Figura 7.11 Escribiendo en un archivo Figura 7.12 Resultado al ejecutar el programa

7.4 Cerrar un archivo

Cuando se ha terminado de trabajar con el archivo, se cierra con la función close(). Esto libera
el archivo para ser usado por otros programas, y además asegura que los cambios sobre él se
guarden. De más está decir que Python se encarga de cerrar todos los archivos que queden abiertos
al final del programa, pero es una buena práctica no dejar nada al azar y cerrar el archivo tan pronto
como se lo termina de usar.
También es recomendable cerrar el archivo al terminar de trabajar por diversos motivos: en
algunos sistemas los archivos sólo pueden ser abiertos por un programa por la vez; en otros, lo que
se haya escrito no se guardará realmente hasta no cerrar el archivo; o el límite de cantidad de
archivos que puede manejar un programa puede ser bajo, etc.
El programa de la figura 7.13 utiliza la función close(). El resultado al ejecutar el programa se
presenta en la figura 7.14.

 248 
Figura 7.13 Cerrando un archivo Figura 7.14 Resultado al ejecutar el programa

7.5 Eliminar datos de un archivo

No existe una función, como tal, para eliminar alguna línea en un archivo. Lo que se tiene que
hacer es leer línea por línea y buscar en cada una que no coincida con la línea que se quiere eliminar,
y si es así se guarda todo en la variable contenida (que declare previamente como una cadena vacía)
y cuando se encuentra la coincidencia la línea no entra la condición establecida y no se guarda en
contenido, siendo así como se elimina la línea. El último paso es sobrescribir en el archivo la
variable con todo el contenido almacenado y la línea se habrá eliminado.
Para hacer esto primero se deben tener algunas consideraciones iniciales, la primera es que es
necesario el uso de la función split(“,”), que indica que los elementos de cada línea están
delimitados por comas. Si se tuviera algún delimitador diferente se tendría que indicar.
Luego se tiene que asignar el valor de cada elemento de la línea a una variable, para estos hay
dos formas de hacerlos, tal como muestra en las figuras 7.15 y 7.16.

Figura 7.15 Utilizando split() Figura 7.16 Utilizando split()


Posteriormente se sigue con el procedimiento mencionado anteriormente, tal como se
muestra en el programa de la figura 7.17. El resultado al ejecutar el programa se presenta en la
figura 7.18.

 249 
Figura 7.17 Eliminando datos Figura 7.18 Resultado al ejecutar el programa

7.7 Modificar datos de un archivo


Tampoco existe una función para modificar los datos de un archivo, lo que se tiene que hacer es
un procedimiento similar al del borrado, con excepción de la comparación, que en este caso si debe
coincidir con el dato a modificar y los demás datos dejarlos iguales. En el programa de la figura
7.19 se muestra cómo modificar un dato en particular. El resultado de su ejecución se observa en
la figura 7.20.

Figura 7.19 Modificando datos

 250 
Figura 7.20 Resultado al ejecutar el programa

7.8 Omitiendo el encabezado de un archivo

Cuando hay datos como encabezados de los nombres de los elementos de las líneas en un
archivo, que vienen en la primera línea, estos no son necesario procesarlos, por lo que hay que
omitirlos.
Para hacer esto hay que “brincar” el contenido de la primera línea, esto se puede hacer de dos
formas. La primera es utilizar un contador que cuando sea 1, pase por alto el contenido de la primera
línea, tal como se muestra en el programa de la figura 7.21. El resultado de su ejecución se presenta
en la figura 7.22.

Figura 7.21 Eliminando datos Figura 7.22 Resultado al ejecutar el programa


La segunda es comparando alguno de los títulos de dicho encabezado contra una variable que
tenga un valor igual. Un ejemplo de este caso se muestra en el programa de la figura 7.23, mientras
que el resultado al ejecutarlo se tiene en la figura 7.24.

 251 
Figura 7.23 Eliminando datos Figura 7.24 Resultado al ejecutar el programa
Como se ve, en ambos casos se utiliza la función strip(), la cual retorna una copia de una cadena
con ciertos caracteres eliminados de su principio y final. En este caso elimina el carácter de fin de
línea. Si no se elimina se tendría una línea en blanco después de imprimir cada línea, tal como se
muestra en el programa de la figura 7.24. El resultado de su ejecución se presenta en la figura 4.26.

Figura 7.25 Eliminando datos Figura 7.26 Resultado al ejecutar el programa

7.9 Actividades a realizar

Codificar y ejecutar en Python los programas para los problemas indicados en cada caso, además
de seguir las indicaciones y/o restricciones si las hubiera. En cada problema se muestran una o
varias figuras con posibles resultados de salida al ejecutar el programa. Todos los problemas deben
ser resueltos utilizando funciones.
Capturar en un archivo de texto todos los estados de la República Mexicana con los siguientes
datos: nombre del estado, abreviatura ISO, capital, fecha de creación del estado, población y
superficie. En el mismo los elementos de cada línea deben estar separados por comas. Parte de
dicho archivo se muestra en la figura 7.27.

 252 
Figura 7.27 Parte del archivo con los datos de los estados
Además se debe realizar un programa que tenga las siguientes opciones: 1. Mostrar todos los
estados; 2. Estado con menor población; 3. Estado con mayor población; 4. Estado con menor
superficie; 5. Estado con mayor superficie; 6. Elegir un estado en particular; 7. Total de la
Población en México; 8. Promedio de habitantes en México; 9. Muestra y guarda en archivo los
estados con más de 2 millones de habitantes. Se debe de utilizar una función para cada opción. Las
opciones deben estar en forma de menú. El programa debe de regresar al menú después de haber
mostrado el resultado correspondiente. Solamente se podrá salir del programa utilizando la opción
10. Cuando se muestran datos de los estados se debe formatear la salida para que los mismos se
presenten alineados, como se muestra en la figura 7.28.

Figura 7.28 Datos de salida formateados


En el caso de la opción 9, la salida se debe mostrar en la pantalla y almacenar en un archivo de
texto con las mismas características que el archivo original, como se muestra en parte de dicho
archivo en la figura 7.29.

Figura 7.29 Parte del archivo de salida de la opción 9.

 253 
Algunos posibles resultados son mostrados en la figura 7.30.

Figura 7.30 Posibles resultados al ejecutar el programa

 254 
Unidad 8 Errores y excepciones
Hasta ahora los mensajes de error no habían sido más que mencionados, pero a los largo del
documento se han visto algunos. Hay (al menos) dos tipos diferentes de errores: errores de sintaxis
y excepciones.

8.1 Errores de sintaxis

Los errores de sintaxis, también conocidos como errores de interpretación, son quizás el tipo de
queja más común que se tienen cuando todavía estás aprendiendo Python, o cualquier lenguaje de
programación. Un mensaje de error de sintaxis de produce (figura 8.2) al ejecutar el programa de
la figura 8.1.

Figura 8.1 Generando un error de sintaxis Figura 8.2 Resultado al ejecutar el programa

8.2 Excepciones

Incluso si la declaración o expresión es sintácticamente correcta, puede generar un error cuando


se intenta ejecutarla. Los errores detectados durante la ejecución se llaman excepciones, y no son
incondicionalmente fatales: pronto se aprenderá cómo manejarlos en los programas en Python. Sin
embargo, la mayoría de las excepciones no son manejadas por los programas, y resultan en
mensajes de error como los mostrados en las figuras 8.4, 8.6 y 8.8, al ejecutar los programas de las
figuras 8.3, 8.5 y 8.7 respectivamente.

Figura 8.3 Generando un error de ejecución Figura 8.4 Resultado al ejecutar el programa

 255 
Figura 8.5 Generando un error de ejecución Figura 8.6 Resultado al ejecutar el programa

Figura 8.7 Generando un error de ejecución Figura 8.8 Resultado al ejecutar el programa
Las excepciones vienen de distintos tipos, y el tipo se imprime como parte del mensaje: los tipos
en son: ZeroDivisionError en la figura 8.4, NameError en la figura 8.6 y TypeError en la figura
8.8. La cadena mostrada como tipo de la excepción es el nombre de la excepción predefinida que
ocurrió. Esto es verdad para todas las excepciones predefinidas del intérprete, pero no necesita ser
verdad para excepciones definidas por el usuario (aunque es una convención útil). Los nombres de
las excepciones estándar son identificadores incorporados al intérprete (no son palabras clave
reservadas).
El resto de la línea provee un detalle basado en el tipo de la excepción y qué la causó.
La parte anterior del mensaje de error muestra el contexto donde la excepción sucedió, en la
forma de un trazado del error listando líneas fuente; sin embargo, no mostrará líneas leídas desde
la entrada estándar.

8.3 Manejo de excepciones

Es posible escribir programas que manejen determinadas excepciones. El programa de la figura


8.9 solicita al usuario una entrada hasta que ingrese un entero válido. El resultado el ejecutarlo se
muestra en la figura 8.10.

Figura 8.9 Manejando excepciones Figura 8.10 Resultado al ejecutar el programa

 256 
La declaración try funciona de la siguiente manera:
Primero, se ejecuta el bloque try (el código entre las declaración try y except).
• Si no ocurre ninguna excepción, el bloque except se saltea y termina la ejecución de la
declaración try.
• Si ocurre una excepción durante la ejecución del bloque try, el resto del bloque se salte. Luego,
si su tipo coincide con la excepción nombrada luego de la palabra reservada except, se ejecuta
el bloque except, y la ejecución continúa luego de la declaración try.
• Si ocurre una excepción que no coincide con la excepción nombrada en el except, esta se pasa
a declaraciones try de más afuera; si no se encuentra nada que la maneje, es una excepción no
manejada, y la ejecución se frena con un mensaje como los mostrados anteriormente.
Una declaración try puede tener más de un except, para especificar manejadores para distintas
excepciones. A lo sumo un manejador será ejecutado. Sólo se manejan excepciones que ocurren en
el correspondiente try, no en otros manejadores del mismo try. Un except puede nombrar múltiples
excepciones usando paréntesis, como se muestra en el programa de ls figura 8.11. El resultado al
ejecutarlo se observa en la figura 8.12.

Figura 8.11 Manejando excepciones Figura 8.12 Resultado al ejecutar el


programa
El último except puede omitir nombrar qué excepción captura, para servir como comodín. Esto
hay que utilizarlo con extremo cuidado, ya que de esta manera es fácil ocultar un error real de
programación. También puede usarse para mostrar un mensaje de error y luego re-generar la
excepción (permitiéndole al que llama, manejar también la excepción).
En el programa de la figura 8.13 se muestra otra forma de manejar excepciones, en donde
dependiendo de cuál sea la excepción se puede mostrar un mensaje diferete, además en la última
excepción se puede mostrar cuando se presente un error inesperado. Es muy útil importar el módulo
sys cuando se maneran excepciones del sistema. El resultado al ejecutarlo se muestra en la figura
8.14, el cual indica que no existe el archivo o directorio a abrir.

 257 
Figura 8.13 Manejando excepciones Figura 8.14 Resultado al ejecutar el programa
Como se observa en la última línea del programa aparece una nueva declaración raise, más
adelante se hablará sobre ella.
Las declaraciones try... except tienen un bloque else opcional, el cual, cuando está presente,
debe seguir a los except. Es útil para aquel código que debe ejecutarse si el bloque try no genera
una excepción. En el programa de la figura 8.15 hace uso de else. Como no existe el archivo
entonces el resultado de su ejecución mostrado en la figura 6.16, es el mismo que el de la figura
8.14.

Figura 8.15 Manejo de excepciones utilizando else Figura 8.16 Resultado al ejecutar el programa
El uso de else es mejor que agregar código adicional en el try porque evita capturar
accidentalmente una excepción que no fue generada por el código que está protegido por la
declaración try... except.
Cuando ocurre una excepción, puede tener un valor asociado, también conocido como el
argumento de la excepción. La presencia y el tipo de argumento dependen del tipo de excepción.

 258 
Si una excepción tiene argumentos, estos se imprimen como la última parte (el ‘detalle’) del
mensaje para las excepciones que no están manejadas.
Los manejadores de excepciones no manejan solamente las excepciones que ocurren en el
bloque try, también manejan las excepciones que ocurren dentro de las funciones que se llaman
(inclusive indirectamente) dentro del bloque try. Por ejemplo, el programa de la figura 8.17 hace
uso del manejo de las excepciones. El resultado al ejecutarlo se presenta en la figura 8.18.

Figura 8.17 Manejo de argumentos de las Figura 8.18 Resultado al ejecutar el programa
excepciones

8.4 Levantando excepciones

La declaración raise permite al programador forzar a que ocurra una excepción específica. El
programa de la figura 8.19 forza la ejecución de una excepción. El resultado al ejecutar el programa
se presenta en la figura 8.20.

Figura 8.19 Forzando una excepción Figura 8.20 Resultado al ejecutar el programa
El único argumento a raise indica la excepción a generarse. Tiene que ser o una instancia de
excepción, o una clase de excepción (una clase que hereda de Exception). Si se pasa una clase de
excepción, la misma sera instanciada implicitamente llamandoa su constructor sin argumentos:
raise ValueError # atajo para 'raise ValueError()'
Si es necesario determinar cuando una excepción fue lanzada pero no se pretende manejarla,
una forma simplificada de la instrucción raise permite relanzarla:

 259 
Figura 8.21 Forzando una excepción Figura 8.22 Resultado al ejecutar el programa

8.5 Cláusula finally


Una cláusula finally siempre es ejecutada antes de salir de la declaración try, ya sea que una
excepción haya ocurrido o no. Cuando ocurre una excepción en la cláusula try y no fue manejada
por una cláusula except (u ocurrió en una cláusula except o else), es relanzada luego de que se
ejecuta la cláusula finally. El finally es también ejecutado “a la salida” cuando cualquier otra
cláusula de la declaración try es dejada vía break, continue o return. En el programa de la figura
8.23 se muestra el uso de dicha cláusula.

Figura 8.23 Cláusula finally


En la tabla 8.1 se muestran tres diferentes llamados a la función dividir, mostrada en el programa
de la figura 8.23. Dependiendo de dichos valores son los resultados mostrados.
Como se puede ver, la cláusula finally es ejecutada siempre.

 260 
Tabla 8.1 Diferentes llamadas a la función dividir
Llamada a la función dividir() Resultado
dividir(1, 0)

dividir(3, 8.0)

dividir(“a”, 8.0)

En aplicaciones reales, la cláusula finally es útil para liberar recursos externos (como archivos
o conexiones de red), sin importar si el uso del recurso fue exitoso.

8.6 Excepciones disponibles

Por último, a continuación se listan las excepciones disponibles por defecto, así como la clase
de la que deriva cada una de ellas, entre paréntesis.
• BaseException: Clase de la que heredan todas las excepciones.
• Exception(BaseException): Super clase de todas las excepciones que no sean de salida.
• GeneratorExit(Exception): Se pide que se salga de un generador.
• StandarError(Exception): Clase base para todas las excepciones que no tengan que ver con salir
del intérprete.
• ArithmeticError(StandardError): Clase base para los errores aritméticos.
• FloatingPointError(ArithmeticError): Error en una operación de coma flotante.
• OverflowError(ArithmeticError): Resultado demasiado grande para poder representarse.
• ZeroDivisionError(ArithmeticError): Lanzada cuando el segundo argumento de una operación
de división o módulo era 0
• AssertionError(StandardError): Falló la condición de un estamento assert.
• AttributeError(StandardError): No se encontró el atributo.
• EOFError(StandardError): Se intentó leer más allá del final de fichero.
• EnvironmentError(StandardError): Clase padre de los errores relacionados con la entrada/salida.
• IOError(EnvironmentError): Error en una operación de entrada/salida.
• OSError(EnvironmentError): Error en una llamada a sistema.
• WindowsError(OSError): Error en una llamada a sistema en Windows.

 261 
• ImportError(StandardError): No se encuentra el módulo o el elemento del módulo que se quería
importar.
• LookupError(StandardError): Clase padre de los errores de acceso.
• IndexError(LookupError): El índice de la secuencia está fuera del rango posible.
• KeyError(LookupError): La clave no existe.
• MemoryError(StandardError): No queda memoria suficiente.
• NameError(StandardError): No se encontró ningún elemento con ese nombre.
• UnboundLocalError(NameError): El nombre no está asociado a ninguna variable.
• ReferenceError(StandardError): El objeto no tiene ninguna referencia fuerte apuntando hacia él.
• RuntimeError(StandardError): Error en tiempo de ejecución no especificado.
• NotImplementedError(RuntimeError): Ese método o función no está implementado.
• SyntaxError(StandardError): Clase padre para los errores sintácticos.
• IndentationError(SyntaxError): Error en la indentación del archivo.
• TabError(IndentationError): Error debido a la mezcla de espacios y tabuladores.
• SystemError(StandardError): Error interno del intérprete.
• TypeError(StandardError): Tipo de argumento no apropiado.
• ValueError(StandardError): Valor del argumento no apropiado.
• UnicodeError(ValueError): Clase padre para los errores relacionados con unicode.
• UnicodeDecodeError(UnicodeError): Error de decodificación unicode.
• UnicodeEncodeError(UnicodeError): Error de codificación unicode.
• UnicodeTranslateError(UnicodeError): Error de traducción unicode.
• StopIteration(Exception): Se utiliza para indicar el final del iterador.
• Warning(Exception): Clase padre para los avisos.
• DeprecationWarning(Warning): Clase padre para avisos sobre características obsoletas.
• FutureWarning(Warning): Aviso. La semántica de la construcción cambiará en un futuro.
• ImportWarning(Warning): Aviso sobre posibles errores a la hora de importar.
• PendingDeprecationWarning(Warning): Aviso sobre características que se marcarán como
obsoletas en un futuro próximo.
• RuntimeWarning(Warning): Aviso sobre comportmaientos dudosos en tiempo de ejecución.
• SyntaxWarning(Warning): Aviso sobre sintaxis dudosa.

 262 
• UnicodeWarning(Warning): Aviso sobre problemas relacionados con Unicode, sobre todo con
problemas de conversión.
• UserWarning(Warning): Clase padre para avisos creados por el programador.
• KeyboardInterrupt(BaseException): El programa fué interrumpido por el usuario.
• SystemExit(BaseException): Petición del intérprete para terminar la ejecución.

8.7 Actividades a realizar


Algunas excepcionese serán utilizadas en el trabajo final, por lo que en esta unidad no se
realizarán actividads de dicho concepto.

 263 
Trabajo final
Codificar y ejecutar en Python los siguientes algoritmos, además de seguir las indicaciones y/o
restricciones si las hubiera. Todos los algoritmos deben ser resueltos utilizando funciones. Además
deben estar incluidos en un menú y el usuario decida cuál utilizar las veces que sea necesario. La
ejecución del programa se terminará cuando se dé la opción “salir”. Se deben utilizar excepciones
cuando se van a introducir listas o elementos a buscar, en todos los casos son siempre números
naturales. En los algoritmos de la burbuja y de mezclas, no solamente mostrar los datos de salida
en pantalla, también se deben de guardar en un archivo.

1) Algoritmo de Euclides
Entrada: dos números enteros m y n.
Paso 1. Dividir m entre n y sea r el residuo. (0  r  n).
Paso 2. Si r = 0, la respuesta es n. FIN.
Paso 3. Asignar m  n, n  r. Volver al paso 1.
Salida: el mcd de m y n.

2) Algoritmo máximo versión 1.


Entrada: Una lista L = {a1, a2,..., an} donde ai  ℕ.
Paso 1. m  a1.
Paso 2. a  a2.
Paso 3. Si a > m entonces m  a.
Paso 4. Mientras queden elementos volver al paso 2.
Salida: El máximo es m.

3) Algoritmo máximo versión 2


Entrada: Una lista L = {a1, a2,..., an} donde ai  ℕ.
Paso 1: Almacenar los n números en n variables v1,..., vn
Paso 2: Asignar m  v1, i  2.
Paso 3: Si m > vi entonces i  i + 1. En caso contrario m  vi + 1, i  i + 1.
Paso 4: Si i > n FIN. En caso contrario volver al paso 3.
Salida: El máximo es m.

 264 
4) Algoritmo repetido versión 1.
Entrada: una lista L = {a1, a2,..., an} de números ordenados de menor a mayor
Paso 1. i  1; j  2.
Paso 2. Si ai = aj entonces la respuesta es SI. FIN
Paso 3. Si j < n entonces i  i + 1; j  j + 1 y volver al paso 2.
Paso 4. La respuesta es NO. FIN.

5) Algoritmo repetido versión 2.


Entrada: una lista L = {a1, a2,..., an} de números ordenados de menor a mayor
Paso 1. i  1; j  2.
Paso 2. Si ai = aj entonces la respuesta es SI. FIN
Paso 3. Si j < n entonces j  j + 1 y volver al paso 2.
Paso 4. Si i < n  1 entonces i  i + 1; j  i +1 y volver al paso 2.
Paso 5. La respuesta es NO. FIN.

6) Algoritmo de búsqueda secuencial.


Entrada: La lista L = {a1, a2,..., an} con n números naturales y un número natural x.
Paso 1. Asignar i  1 (inicialización de variable).
Paso 2. Si ai = x entonces la respuesta es “SI”. FIN.
Paso 3. Si i < n entonces asignar i  i + 1 y volver al paso 2.
Paso 4. La respuesta es “NO”. FIN.

7) Algoritmo de la burbuja
Entrada: Una lista L = {a1, a2,..., an} de n número naturales.
Paso 1. Asignar j  n, i  1.
Paso 2. Si i < j entonces si ai > ai+1 intercambiar ai con ai+1. En caso contrario, es decir, i  j,
ir al paso 4.
Paso 3. i  i + 1 y volver al paso 2.
Paso 4. Si j > 2 asignar j  j – 1 y i  1 y volver al paso 2.
Paso 5. FIN.
Salida: La lista L esta ordenada.

 265 
8) Algoritmo búsqueda (binaria)
Entrada: La lista L = {ai, ai+1,..., aj} con n números naturales ordenados de menor a mayor y
un número natural x.
Paso 1. Si i = j comparar ai con x. Si ai = x. la respuesta es “SI” y termina el algoritmo. Si ai 
x, la respuesta es “NO” y termina el algoritmo.
Paso 2. Asignar m [(i + j) / 2] (que representa al mayor entero menor que (i + j) / 2), es decir,
aproximadamente el elemento medio.
Paso 3. Comparar x con am. Si x = am, la respuesta es “SI” y termina el algoritmo.
Paso 4. Si x < am asignar j  m - 1 y volver al paso 1.
Paso 5. Si x > am asignar i  m + 1 y volver al paso 1.

9) Algoritmo mezclas
Entrada: Dos listas L1 = {a1, a2,..., ar} y L2 = {b1, b2,..., bs} con r y s números respectivamente,
ordenados de menor a mayor.
Paso 1. Asignar i  1, j  1, k  1.
Paso 2. a) Si ai  bj entonces asignar ck  ai y si i < r asignar i  i + 1. En caso contrario
ck  bj y si j < s, asignar j j + 1.
b) Si i = r asignar ar  bs y si j = s asignar bs  ar.
Paso 3. Asignar k  k + 1.
Paso 4. Si k  r + s entonces volver al paso 2.
Paso 5. FIN.
Salida: L = {c1, c2,..., cr+s}

 266 

S-ar putea să vă placă și