{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![](img/logocurso.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "nbpresent": {
     "id": "d9e822f9-0a52-43f2-90ef-e8fd6860aacc"
    }
   },
   "source": [
    "![](img/sesion1.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "nbpresent": {
     "id": "5d022e4f-c1f2-4991-b1d0-763579c07a45"
    }
   },
   "source": [
    "Tal y como se afirma en la documentación original de la web oficial de Phython, el nombre del lenguaje no guarda relación alguna con los reptiles y se debe a la serie de humor de la BBC “Monty Python’s Flying Circus” que fue emitida alrededor de 1970. Los autores de los manuales oficiales de Phython animan a recordar este hecho con las siguientes palabras:  \"Making references to Monty Python skits in documentation is not only allowed, it is encouraged!\"\n",
    "\n",
    "Una pequeña muestra de tales skits:\n",
    "https://www.bing.com/videos/search?q=monty+python%e2%80%99s+flying+circus&&view=detail&mid=D3F1C030A1BC99435001D3F1C030A1BC99435001&FORM=VRDGAR\n",
    "\n",
    "\n",
    "Python es un lenguaje de programación:\n",
    "\n",
    "* Interpretado e Interactivo\n",
    "* Fácil de aprender, programar y **leer** (menos *bugs*)\n",
    "* De *muy alto nivel*\n",
    "* Multiparadigma\n",
    "* Orientado a objetos\n",
    "* Libre y con licencia permisiva\n",
    "* Eficiente\n",
    "* Versátil y potente! \n",
    "* Con gran documentación\n",
    "* Y una gran comunidad de usuarios\n",
    "* Dispone de paquetes para el tratamiento simbólico y numéricos de expresiones y algoritmos matemáticos.\n",
    "\n",
    "<div class=\"alert alert-info\"><b>Las versiones de Python:</b> Como para cualquier otro lenguaje de programación, diferentes versiones del lenguaje se han sucedido a lo largo de los últimos años. En la actualidad se utilizan de forma activa en la programación dos de ellas:\n",
    "<ul>\n",
    "<li>Python 2.x: Aunque es una implementación más antigua tiene gran número de paquetes y librerías disponibles y testadas por lo que son muchos los programadores que continuan utilizándola.</li>\n",
    "<li>Python 3.x: Es la última versión estable y testada del lenguaje y empieza a consolidarse como el estándar de referencia.</li>\n",
    "</ul>\n",
    "</div>\n",
    "\n",
    "\n",
    "\n",
    "## Como usar Python\n",
    "\n",
    "### Interprete/consola/entorno de programación\n",
    "\n",
    "Para poder utilizar el lenguaje Python el elemento esencial es:\n",
    "<div class=\"alert alert-info\"><b>Un interprete:</b> Python es un lenguaje interpretado, eso significa que sus instrucciones no son comprensiblemes de forma directa para el microprocesador del sistema, el cerebro del ordenador. El intérprete es capaz de leer instrucciones escritas en el lenguaje de Python y de traducirlas al lenguaje del microprocesador.</div>\n",
    " \n",
    "El interprete puede recibir las instrucciones Python de dos formas:\n",
    "* **Mediante una consola Python:** Una consola Python es una ventana en la que se pueden escribir instrucciones que son mandadas sobre la marcha a Python que las ejecuta en el momento. Es como una calculadora en la que en lugar de las operaciones matemáticas normales se pueden ejecutar instrucciones escritas en Python.\n",
    "* **Mediante un fichero .py (script Python):** En lugar de ejecutar instrucciones una a una, podemos agruparlas todas en un fichero (generalmente con la extensión .py). Es lo que en la terminología común se denominaría como \"un programa Python\". El interprete recibe el fichero .py y ejecuta todas sus instrucciones. Podemos preparar el fichero .py con cualquier editor pero lo ideal es disponer de uno especialmente diseñado para trabajar con instrucciones Python y que sea capaz de asistirnos en la confección del código, un editor Python.\n",
    "\n",
    "<div class=\"alert alert-info\">Un <b>entorno de programación Python</b> es un sistema que integra:\n",
    "<ul>\n",
    "<li>Un interprete Python.</li>\n",
    "<li>Un editor Python.</li>\n",
    "<li>Una consola Python.</li>\n",
    "</ul>\n",
    "</div>\n",
    "\n",
    "\n",
    "<div class=\"alert alert-info\" style=\"color:black; background-color:rgb(200,150,150)\">El entorno de programación que nosotros utilizaremos es: <b>Spyder</b></div>\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "### Notebooks/IPython y Jupyter\n",
    "\n",
    "\n",
    "<div class=\"alert alert-info\">\n",
    "<ul>\n",
    "    <li><b>IPython</b> es un formato que permite integrar en un mismo documento textos, codigo ejecutable Python, gráficos y otros muchos tipos de elementos. Con este formato se pueden elaborar documentos interactivos que se denominan  Notebooks. </li>\n",
    "    <li>Un <b>notebook</b> es, por tanto, un documento interactivo que incluye texto, gráficos y código (fragmentos de programas) que al ejecutarse articulan esa interactividad. Para que un notebook pueda mostrarse adecuadamente es preciso disponer de un sistema (presenter) que conecte el notebook con un interprete que ejecute el código que incluye.</li>\n",
    "    <li><b>Jupyter</b> es un sistema web para presentar Notebooks elaborados en IPython (un IPython notebook presenter) que permiter concectar con intérpretes o núcleos de distintos lenguajes para ejecutar el código interactivo que contengan esos notebooks.</li>\n",
    "</ul>\n",
    "</div>\n",
    "\n",
    "El documento que aparece ahora mismo en pantalla es un notebook de IPhython que es mostrado por Jupyter.\n",
    "\n",
    "\n",
    "\n",
    "## Anaconda\n",
    "\n",
    "Los elementos que utlizaremos forman un paquete de aplicaciones integrado por\n",
    "* El interprete Python.\n",
    "* Spyder.\n",
    "* Jupyter.\n",
    "* Otras herramientas de gestión de paquetes (grupos de instrucciones que añaden instrucciones adicionales a Python).\n",
    "\n",
    "<div class=\"alert alert-info\" style=\"color:black; background-color:rgb(200,150,150)\">Todos estas herramientas agrupadas pueden encontrarse dentro de un paquete de aplicaciones para la programación en Python denominado <b>Anaconda</b>.</div>\n",
    "\n",
    "Anaconda permite instalar como una sola aplicación todos estos elementos y además incorpora herramienta de panel de contror **Anaconda Navigator** que permite gestionarlos de forma conjunta.\n",
    "\n",
    "\n",
    "### Instalación\n",
    "\n",
    "Mediante los siguientes links accedemos a la página oficial de anaconda y a la sección de descargas desde donde podemos instalar el software:\n",
    "* **http://anaconda.com**\n",
    "* **https://www.anaconda.com/download/**\n",
    "\n",
    "En la actualidad se ofrece de forma gratuita la \"Individual Edition\" de 64-bits asociada a Python 3.9\n",
    "<img src=\"img/ins01.png\" width=\"300\">\n",
    " \n",
    "\n",
    "\n",
    "Una vez descargado, lo instalaremos siguiendo las indicaciones del asistente y utilizando las opciones por defecto\n",
    "<img src=\"img/ins03.png\" width=\"400\">\n",
    "y si todo el proceso discurre correctamente dispondremos entonces de un completo paquete de programación Python cuyas herramientas esenciales son **Anaconda Navigator**, **Jupyter Notebook** y **Spyder**:\n",
    "<img src=\"img/ins04.png\" width=\"200\">\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Anaconda Navigator\n",
    "\n",
    "*Anaconda Navigator* es un panel de control desde el que pueden manejarse todas las herramientas que integran Anaconda. Dispone de una interfaz visual que hace posible lanzar la aplicación que deseemos utilizar. El menú lateral incluye las siguientes opciones:\n",
    "* <b>Home:</b> que muestra la lista de herramientas disponibles y permite ejecutarlas pulsando, en cada caso, el correspondiente botón \"Launch\".\n",
    "* <b>Environments:</b> para el control de los \"packages\" o paquetes que extienden las funcionalidades de Python.\n",
    "* <b>Learning:</b> pone a nuestra disposición toda una biblioteca de documentación sobre Python, Anaconda y las herramientas que integra.\n",
    "* <b>Comunity:</b> panel que reune eventos y noticias de interés para la comunidad de programadores Python y usuarios de Anaconda.\n",
    "\n",
    "\n",
    "![](img/anaconda01.png)\n",
    "\n",
    "\n",
    "<div class=\"alert alert-info\">\n",
    "    Los <b>\"packages\"</b> o paquetes son extensiones del lenguaje Python que permiten incorporar nuevos grupos de instrucciones que añaden funcionalidades adicionales concretas. Existen paquetes gráficos que incorporan instrucciones para el manejo de imágnenes, paquetes de seguridad que permiten la encriptación y envío seguro de información, paquetes para conectar Python con otros lenguajes, paquetes incluso para conectar Python con servicios como Amazon o Twitter. A nosotros nos interesarán, por supuesto, los paquetes matemáticos de que dispone Python. Mediante la herramienta <b>Environments</b> del menú lateral de Anaconda podemos gestionar los paquetes que tenemos disponibles, actualizarlos o añadir otros nuevos.\n",
    "\n",
    "Los paquetes matemáticos que nosotros utilizaremos serán:\n",
    "<ul>\n",
    "    <li><b>Sympy:</b> Orientado al manejo y tratamiento simbólico de expresiones matemáticas.</li>\n",
    "    <li><b>Numpy:</b> Incorpora instrucciones para el tratamiento numérico y manejo de matrices multidimensionales (multi-matrices), álgebra lineal, series de Fourier y números aleatorios.</li>\n",
    "</ul>\n",
    "</div>\n",
    "\n",
    "Podemos utilizar Environments para comprobar que estos dos paquetes están ya instalados por defecto en el sistema.\n",
    "![](img/anaconda02.png)\n",
    "\n",
    "<div class=\"alert alert-info\">\n",
    "    <b>Anaconda Cloud</b> es un servicio que permite compartir notebooks, packages, scripts y proyectos en la nube. El servicio es gratuito siempre y cuando el material se comparta en abierto (accesible libremente a toda la comunidad de usuarios) aunque existen modalidades de pago que permiten estipular restricciones de acceso. Es imprescindible registrarse en el servicio indicando login, password y un email. La operación de registro es sencilla y rápida.\n",
    "</div>\n",
    "\n",
    "En la parte superior derecha de Anaconda Navigator encontramos un botón de acceso a Anaconda Cloud mediante el que puede conectarse a una cuenta ya existente o registrarse un nuevo usuario.\n",
    "![](img/anaconda03.png)\n",
    "<br>Una vez conectado, podemos subir y bajar nuestros paquetes de la nuve utilizando Anaconda Prompt.\n",
    "<img src=\"img/anaconda04.png\" width=\"200\">\n",
    "Desde Anaconda Prompt, para subir uno de nuestros paquetes, escribiremos\n",
    "![](img/anaconda05.png)\n",
    "y para descargar un paquete realizado por otro usuario,\n",
    "![](img/anaconda06.png)\n",
    "\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "nbpresent": {
     "id": "7887b9f1-ee09-4b1f-b5ee-ec462b0a99bc"
    }
   },
   "source": [
    "## Jupyter Notebook\n",
    "\n",
    "Una forma sencilla de utilizar Python es usar los *Notebooks* de Jupyter. \n",
    "\n",
    "<div class=\"alert alert-info\"><em>Jupyter</em> (=Julia+Python+R) es un entorno web para computación interactiva que permite conectar con un núcleo que ejecuta código de distintos lenguajes, entre ellos Python.\n",
    "</div>\n",
    "\n",
    "De este modo, si bien nació como parte del proyecto IPython que era exclusivo para Python, en Jupyter el mismo entorno visual se puede conectar a <em>\"kernels\"</em> de distintos lenguajes. Se puede usar Jupyter con Python, Julia, R, Octave y decenas de lenguajes más.\n",
    "\n",
    "Un Notebook es un documento JSON que incluye una sucesión ordenada de entradas y salidad que Jupyter muestra como celdas. Estas celdas pueden contener código ejecutable e interactivo, gráficos, texto, fórmulas y otros elementos web. Los documentos de Jupyter se guardan con la extensión <em>.ipynb</em>. Podemos salvarlos para reutilizarlos en otro momento o en otro equipo.\n",
    "\n",
    "Dese 2020 IPython y Jupiter dejaron de ser compatibles con Python 2 y en la actualidad solamente soporta la coneción con núcleos de Python 3.\n",
    "\n",
    "\n",
    "### ¿Cómo utilizar Jupyter? \n",
    "\n",
    "Jupyter se utiliza desde un explorador web. Para conectar nuestro browser con un núcleo de Python (u otro lenguaje) y poder disfrutar de las capacidades interactivas de Jupyter disponemos de dos posibilidades:\n",
    "<ul>\n",
    "    <li>Instalando tanto Jupyter como un núcleo de Python en nuestro equipo. En nuestro caso Anaconda hará todo esto por nosotros y, además, enlazará convenientemente todos los componenetes.</li>\n",
    "    <li>Conectando on-line con el sitio oficial de Jypyter y abriendo una sesión de prueba. En este caso, será el servidor de Jupyter el que conectará nuestro browser con un nucleo de Python, Julua, R, C++, Scheme o Ruby. Puede accederse a estos servicios mediante el link: <a href=\"https://jupyter.org/try\">https://jupyter.org/try</a></li>\n",
    "</ul>\n",
    "\n",
    "El material de este curso está elaborado con Jupyter. Los notebook de Jupyter incluyen la información y contenidos que conforman cada sesión junto con ejemplos interactivos y propuestas de ejercicios que resolveremos y ejecutaremos desde el mismo Jupyter. \n",
    "\n",
    "Asimismo, nosotros mismos podremos insertar en cada notebook nuestas propias aclaraciones, comentarios, código Python, podremos salvarlo y conservarlo para continuar nuestro trabajo en otro momento.\n",
    "\n",
    "\n",
    "### Primeros pasos en Jupyter\n",
    "\n",
    "Ejecuta *Jupyter Notebook* desde Anaconda Navigator o desde el menú de inicio de Windows. \n",
    "<table>\n",
    "<tr>\n",
    "    <td><img src=\"img/lanzajupyter1.png\" width=\"300\"></td><td>&nbsp;&nbsp;</td>\n",
    "    <td><img src=\"img/lanzajupyter2.png\" width=\"300\"></td>\n",
    "</tr>\n",
    "</table>\n",
    "\n",
    "Al lanzar la aplicación se abrirá nuestro navegador por defecto mostrando la página de inicio de Jupyter en una pestaña nueva:\n",
    "\n",
    "<img src=\"img/jupyter1.png\" >\n",
    "\n",
    "<br>\n",
    "\n",
    "Jupyter accede por defecto a la carpeta C:\\Usuarios\\UJA\\ dentro de nuestro equipo y nos muestra su contenido. Podemos entonces abrir un fichero de notebook (extensión .ipynb) navegando dentro de las carpetas disponibles o crear uno nuevo. Para crear carpetas donde ubicar nuestros ficheros o nuevos notebooks utilizamos el menú \"New\" a la derecha de la página\n",
    "\n",
    "<img src=\"img/jupyter2.png\" >\n",
    "\n",
    "Antes de crear un nuevo notebook debemos desplazarnos, usando el navegador de Jupyter a la carpeta en que deseemos ubicarlo o, si ello es más conveniente para organizar nuestro trabajo, crear una nueva carmeta (también desde el menú \"New\"). Como vemos, la única opción que nos ofrece dentro \"New\", en la sección \"Notebook\" es \"Python 3\" ya que, gracias a Anaconda, hemos instalado Python 3; si tubiéramos otros nucleos de lenguajes de programación instalados, Jupyter nos ofrecería la posibilidad de asociar el notebook con cualquiera de los lenguajes compatibles presentes en el equipo. \n",
    "\n",
    "\n",
    "<br>\n",
    "\n",
    "Tras pulsa crear un nuevo notebook mediante <b>New/Notebooks/Python 3</b> se abrirá en una nueva pestaña un notebook vacío con una única celda. Puedes observar que en la cabecera se asigna como nombre del notebook \"Untitled (unsaved changes)\". Puedes utilizar la opciòn \"Save as\" dentro del menú <b>File</b> para dar nombre al nuevo notebook de forma similiar a como se hace en cualquier otra aplicación de Windows.\n",
    "\n",
    "![](img/img006.png)\n",
    "\n",
    "Para trabajar con Jupyter simplemente hay que insertar instrucciones en las celdas disponibles y ejecutarlas pulsando la combinación de teclas SHIFT+ENTER. Podemos utilizar la barra de menú o la línea de iconos para insertar nuevas celdas, para reordenarlas, copiarlas o eliminarlas. En el siguiente video realizamos algunas de estas operaciones básicas:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<video width=\"600\"  controls src=\"img/img013.mp4\" />"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Jupyter admite dos tipos fundamentales de celdas:\n",
    "<div class=\"alert alert-info\"><ul>\n",
    "    <li><b>Code:</b> En estas celdas podemos insertar y ejecutar instrucciones Python</li>\n",
    "    <li><b>Markdown:</b> Diseñadas para incluir comentarios, aclaraciones, texto, imágnes, etc. En estas celdas podemos utilizar código HTML o incluso LaTeX para añadir formatos al texto.</li>\n",
    "</ul></div>\n",
    "\n",
    "\n",
    "Las celdas <b>Markdown</b> admiten códigos especials que permiten aplicar formatos de texto, insertar imágenes o videos de forma sencilla. Algunos links que describen el lenguaje Markdown de Jupyter son los siguientes:\n",
    "<ul>\n",
    "<li><a href=\"https://sourceforge.net/p/jupiter/wiki/markdown_syntax/\">https://sourceforge.net/p/jupiter/wiki/markdown_syntax/</a>\n",
    "</li>\n",
    "\n",
    "<li><a href=\"https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet\">https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet</a></li>\n",
    "\n",
    "</ul>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Spyder\n",
    "\n",
    "Spyder es un editor orientado a Python. Es un entorno integrado (editor + intérprete + depurador + ayuda + consola interactiva). Como se aprecia en la siguiente imagen, tiene las funcionalidades habituales de cualquier editor orientado a la programación. Permite escribir, depurar y ejecutar programas escritos en Python. Si echamos un vistazo a la botonera encontraremos las funciones habituales de todos los entornos de programación.\n",
    "\n",
    "![](img/spyder01.png)\n",
    "\n",
    "Abre Spyder e inserta el breve programa que aparece en la imagen superior dentro de la ventana principal. \n",
    "<img src=\"img/sesion1-progcorto.png\" width=\"100\">\n",
    "Ejecuta las instrucciones que has escrito pulsando en el icono \"Ejecutar archivo\",\n",
    "<img src=\"img/sesion1-ejecutar-1.png\" width=\"300\">\n",
    "\n",
    "en la opción de menú \"Ejecutar\"\n",
    "<img src=\"img/sesion1-ejecutar-2.png\" width=\"400\">\n",
    "\n",
    "o, simplemente, pulsando la tecla F5. Los resultados se mostrarán en la ventana \"Terminal\" situada en la esquina inferior derecha.\n",
    "\n",
    "\n",
    "\n",
    "## Ejecutar código Python en este curso\n",
    "\n",
    "Para ejecutar código Python podemos utilizar tanto Jupyter como Spyder y a lo largo del curso recurriremos a ambos. Para ejercicios cortos y los ejemplos básicos, Jupyter es una opción conveniente ya que además permite grabar el notebook de cada sesión con las soluciones que hemos dado a cada ejercicio y los comentarios que consideremos precisos.\n",
    "\n",
    "Cuando deseemos embarcarnos en proyecto más complejo como alguno de los ejercicios que se proponen en las últimas sesiones o el proyecto final de esta parte del curso, Spyder es más adecuado pues es la única manera de manejar con facilidad y precisión scripts complejos.\n",
    "\n",
    "\n",
    "<hr>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# <font size=6 color=\"#AA0000\"><u><b>Introducción a la sintaxis de Python</b></u></font>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-info\">\n",
    "La arquitectura básica de cualquier lenguaje de programación se basa en dos elementos fundamentales:\n",
    "<ul>\n",
    "    <li><b>Las estructuras de datos:</b></li> Que clases de datos podemos manejar para almacenar información: números, listas de números, textos (cadenas de caracteres), imágenes, sonidos, videos, fórmulas matemáticas, etc.\n",
    "    <li><b>Las estructuras de control:</b></li> Cómo se decide qué instrucciones realizar, en qué orden hacerlo y cuándo ejecutarlas.\n",
    "</ul>\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "nbpresent": {
     "id": "dc5a5696-d423-4e9b-95db-bf9c3e9c336b"
    }
   },
   "source": [
    "## Un primer programa simple"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Los siguientes son otros dos ejemplos de programas escritos en Python que ponen de manifiesto una de sus características básicas: la indentación. En Python se usa el alineado a la izquierda (indentación) para delimitar conjuntos de acciones. Por contra, en otros lenguajes de programación esto se hace utilizando caracteres delimitadores.\n",
    "\n",
    "¿Puedes predecir en qué se diferenciarán los resultados de uno y otro? Ejecuta ambas celdas para comprobarlo."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x=0\n",
    "i=1\n",
    "while i<=10:\n",
    "    x+=i\n",
    "    i+=1\n",
    "print (x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x=0\n",
    "i=1\n",
    "while i<=10:\n",
    "    x+=i\n",
    "    i+=1\n",
    "    print (x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Como vemos, Python no necesita llaves, paréntesis o corchetes para agrupar instrucciones. Tampoco hace falta ningún tipo de carácter al final de cada línea."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Aunque la sintaxis de Python permite muchas variaciones, existe una guía de estilo que es recomendable para todo programador de Python. Cuando acabe el curso y antes de empezar a usar Python como tu lenguaje de programación es más que conveniente leerla atentamente:\n",
    "\n",
    "[Guía de estilo de Python: PEP 8](https://www.python.org/dev/peps/pep-0008/)\n",
    "\n",
    "Veamos lo básico para poder escribir programas simples en Python."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Tipos de datos"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Como hemos dicho antes, los tipos, estructuras o clases de datos elementales constituyen los ladrillos básicos de cualquier lenguaje de programación y determinan qué y cómo podremos hacer con ese lenguaje. Los tipos de datos básicos podemos clasificarlos en:\n",
    "* Números.\n",
    "* Variables.\n",
    "* Cadenas de texto.\n",
    "* Listas y tuplas."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Tipos numéricos\n",
    "\n",
    "Los tipos numéricos básicos son:\n",
    "\n",
    "<div class=\"alert alert-info\">\n",
    "    <table>\n",
    "    <tr>\n",
    "        <td><b>Tipo de números</b></td><td><b>Python type</b></td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>Enteros</td><td>int</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>Reales</td><td>float</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>Complejos</td><td>complex</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>Valores booleanos</td><td>bool</td>\n",
    "    </tr>\n",
    "</table>\n",
    "</div>\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "### Enteros (int)\n",
    "Números enteros positivos o negativos. Tenemos los siguientes prefijos modificadores\n",
    "* **0o** indica que el número está en octal\n",
    "* **0x** indica que el número está en hexadecimal"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "11"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "0x10"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Reales (float)\n",
    "Números con decimales. El punto decimal se denota con \".\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "3.23423-12.32423"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Complejos (complex)\n",
    "Los números complejos pueden manejarse de forma estándar en Python con tres notaciones:\n",
    "* a+b j\n",
    "* a+b J\n",
    "* complex(a,b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print((2+3j)*(5-6j),\"o también\",(2+3J)*(5-6J),\"o también\",complex(2,3)*complex(5,-6))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "2+3j"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Valores booleanos (bool)\n",
    "* **True**=verdadero, **False**=falso\n",
    "* Cualquier valor distinto de 0 es True, 0 es False.\n",
    "* Cualquier cosa con longitud distinta de 0 es True, con longitud cero es False."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###  Dos tipos de datos importados (Decimal, Fraction)\n",
    "\n",
    "Aparte de los tipos de datos básicos directamente incorporados en el núcleo del lenguaje de Python, podemos importar paquetes que manejan tipos de datos adicionales que podrían interesarnos. A modo de ejemplo mostramos estos dos tipo de datos que podremos utilizar solamente después de carga el paquete correspondiente ya que no forman parte de los tipos básicos que incorpora Python por defecto\n",
    "\n",
    "#### Reales con precisión arbitraria (Decimal)\n",
    "\n",
    "Para utilizarlos es preciso cargar el módulo **decimal**. Este paquete permite manejar números con un número arbitrariamente grande de decimales. El formato es alguno de los siguientes:\n",
    "* Decimal(\"eeeeee.dddddddd\")\n",
    "* Decimal((s,(d1,d2,d3,d4,d5,d6,d7,d8),-numerodecimales))         (donde s=0 para +, s=1 para -)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from decimal import *\n",
    "\n",
    "Decimal('23.2342342342423424234111111111111111')-Decimal('22.234234234234234')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "Decimal((0,(1,2,3,4,5,4,3,4,3,4,3,2,4,3,2,3,2),-8))*Decimal((1,(1,2,3,4,5,4,3,4,3,4,3,2,4,3,2,3,2),-8))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Podemos fijar la precisión con: getcontext().prec"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(getcontext().prec)\n",
    "getcontext().prec=50\n",
    "print(getcontext().prec)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Fracciones (Fraction)\n",
    "En este caso necesitamos el paquete **fractions**. Podremos manejar fracciones con el formato **Fraction(numerador, denominador)**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from fractions import Fraction\n",
    "print(Fraction(3,7)-Fraction(4,11),\"o también\",Fraction(4,2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Operadores\n",
    "\n",
    "Podemos realizar cálculos con las operaciones básicas. La notación para ellas en Pyton es la siguiente:\n",
    "\n",
    "<div class=\"alert alert-info\">\n",
    "<ul>\n",
    "    <li><b>Operaciones básicas:</b></li>\n",
    "    <table>\n",
    "    <tr>\n",
    "        <td>Suma</td><td>+</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>Resta</td><td>-</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>Producto</td><td>&#42;</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>Potencia</td><td>&#42;&#42;</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>División real</td><td>/</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>División entera</td><td>//</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "        <td>Resto</td><td>%</td>\n",
    "    </tr>\n",
    "</table>\n",
    "    <li><b>Operadores booleanos:</b> and, or, not</li>\n",
    "</ul>\n",
    "</div>\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "2 * 4 - (7 - 1) / 3 + 1.0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Las divisiones por cero lanzan un error:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "1/0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "La división en Python 3.6 siempre produce un número \"float\", con decimales, (en Python 2.7 dependía de los parámetros). La división entera se aplica con el símbolo //."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = 7 / 2\n",
    "y = 7. / 2\n",
    "z = 7//2\n",
    "w = 7%2\n",
    "t = 7/7\n",
    "print (\"x =\",x,\"\\ny =\",y,\"\\nz=\",z,\"\\nw=\",w,\"\\nt=\",t)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Calcular $\\frac{1+\\left(2+\\frac{3}{2}\\right)^4}{5+2\\cdot 3^6}$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Mi primer cálculo\n",
    "(1+(2+3/2)**4)/(5+2*3**6)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "True and False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "not True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "True or False"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Conversión de tipos\n",
    "\n",
    "Podemos transformar datos de un tipo a otro utilizando las siguientes instrucciones:\n",
    "\n",
    "* **int**: convierte a entero\n",
    "* **round**: redondea al entero más próximo\n",
    "* **int**: elimina la parte decimal dejando únicamente la parte entera\n",
    "* **str**: transforma a una cadena de caracteres\n",
    "* **type**: proporciona el tipo de una variable\n",
    "* **isinstance(a,tipo)**: retorna True si a es del tipo indicado y false en caso contrario."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "int(1.56)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "round(1.56)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "str(3.1415926)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = 2.\n",
    "type(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "isinstance(a, float)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<hr style=”height: 10px;”> \n",
    "\n",
    "<div class=\"alert alert-info\">\n",
    "    <span style=\"font-size:20px\" ><b>Nota:</b></span>\n",
    "<ul>\n",
    "<li>Podemos recuperar resultados de algunas celdas usando el guión bajo seguido del número de ejecución.</li>\n",
    "    <li>Los comentarios en Python se realizan encabezándolos con el símbolo #.</li>\n",
    "</ul>\n",
    "</div>\n",
    "                                \n",
    "<hr >"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "3**2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "2 * _ #referecia la celda anterior. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(_60) #imprime la salida número 60"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Algunas funciones matemáticas"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "abs(-20)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "abs(-15+2j)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "max(2,9,3,5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "min(-2,9,3,5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Variables, asignación y operadores de comparación\n",
    "\n",
    "Los nombres de las variables en Python pueden contener caracteres alfanuméricos (empezando con una letra) a-z, A-Z, 0-9 y otros símbolos como el guión bajo  \"\\_\". \n",
    "\n",
    "Por cuestiones de estilo, las variables suelen empezar con minúscula, reservando la mayúcula para clases. \n",
    "\n",
    "No pueden usarse como nombre de variables las palabras clave de Python.\n",
    "\n",
    "La asignación se realiza con el operador `=`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = 1.56\n",
    "b = 1 - 2j\n",
    "x, y = 12, 13.73\n",
    "print (a)\n",
    "print (b)\n",
    "print (x, y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-info\">Es posible la <b>asignación múltiple</b>, tal y como vemos en la celda anterior para las variables x e y.</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x, y = y, x\n",
    "x, y"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Los operadores de comparación son:\n",
    "\n",
    "* `==` igual a\n",
    "* `!=` distinto de \n",
    "* `<` menor que\n",
    "* `<=` menor o igual que\n",
    "* `>` mayor que\n",
    "* `>=` mayor o igual que\n",
    "\n",
    "Devolverán un booleano: `True` o `False`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(x < y)\n",
    "print(x <= y)\n",
    "print(x > y)\n",
    "print(x >= y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Es posible concatenar desigualdades utilizando la notación matemática habitual:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = 5.2\n",
    "6.34 < x < 7.25"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Cadenas de texto\n",
    "Las cadenas de texto se construyen encerrando entre \" \" o ' ' (comillas doble o simples) una lista de caracteres. También se puede emplear como delimitadores \"\"\" \"\"\" y ''' ''' (triples comillas dobles o simples). Algunos modificadores son:\n",
    "* r\"cadena\": Cadena raw o literal en la que no se expanden caracteres de control.\n",
    "* u\"cadena\": Cadena unicode"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"Soy 'Antonio'.\\nPero no soy 'Luis'\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(r\"Soy 'Antonio'.\\nPero no soy 'Luis'\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"\"\"Soy \"Antonio\".\\nTambién 'Fermín' según proceda.\"\"\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Operadores, comparación e indexación de cadenas\n",
    "\n",
    "<div class=\"alert alert-info\">\n",
    "<ul>\n",
    "    <li><b>+</b>: concatena cadenas. Para cadenas constantes concretas la yuxtaposición también produce el concatenado.</li>\n",
    "    <li><b>&#42;</b>: repite una cadena.</li>\n",
    "</ul>\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"hola\"\"adios\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a=\"pica\"\n",
    "b=\"pato\"\n",
    "c=\"guapo\"\n",
    "3*(a+b+2*c)+a"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Las **cadenas de texto** tiene orden alfabético y pueden ser comparadas mediante el orden lexicográfico:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"aarónico\" < \"zuzo\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"aaa\"<\"ab\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-info\">\n",
    "Podemos referirnos a caracteres concretos dentro de una cadena utilizando como índice su posición. Hay que tener en cuenta que en Python <b>la posición inicial se numera como 0</b>.\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"En un país multicolor\"[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-info\">\n",
    "Podemos dividir una cadena de texto en las palabras que la integran mediante:\n",
    "<ul>\n",
    "    <li><b>cadena.split()</b>: por defecto como separador utiliza espacio.</li>\n",
    "    <li><b>cadena.split(\"separador\")</b>: que utiliza el separador que especifiquemos entre las comillas.</li>\n",
    "</ul>\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"hola como estás\".split()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"Esta es la primera frase. Esta la segunda. Esta la tercera.\".split(\".\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Listas y Tuplas\n",
    "\n",
    "El primer tipo de dato complejo que vamos a utilizar en Python son las **tuplas** y **listas** que son a su vez casos particulares de un tipo más general denominado \"secuencias\". Tanto tuplas como lista son conjuntos ordenados de elementos: las tuplas se demarcan con paréntesis y las listas con corchetes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mi_lista = [1, 2, 3.0, 4 + 0j, \"5\"]\n",
    "mi_tupla = (1, 2, 3.0, 4 + 0j, \"5\")\n",
    "print(mi_lista)\n",
    "print(mi_tupla)\n",
    "print(mi_lista == mi_tupla)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "En las tuplas se pueden obviar los parántesis:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tupla_sin_parentesis = 2,5,6,9,7\n",
    "type(tupla_sin_parentesis)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Funciones con secuencias\n",
    "\n",
    "Podemos comprobar si un elemento está en la secuencia con el operador `in`, saber su longitud con la función *len* :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "2 in mi_lista"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "2 not in mi_tupla"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "len(mi_lista)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "len(mi_tupla)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Se pueden insertar y eliminar elementos en una lista con *insert*, *append*, *extend*, *remove* y *pop*, así como unir varias listas o tuplas mediante el operador *+*:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mi_lista.insert(3,3.5)\n",
    "mi_lista"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mi_lista=[1, 2, 3.0, 3.5, (4+0j), '5']\n",
    "mi_lista.append(6)\n",
    "print (mi_lista)\n",
    "mi_lista.extend([7, 8])\n",
    "print (mi_lista)\n",
    "mi_lista.insert(0, 0.0)\n",
    "print (mi_lista)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mi_lista.remove(3.5)\n",
    "print (mi_lista)\n",
    "dato = mi_lista.pop(0)\n",
    "print (dato)\n",
    "dato = mi_lista.pop()\n",
    "print (dato)\n",
    "print (mi_lista)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# concatenar listas y tuplas\n",
    "\n",
    "lista1=[1, 2, 3]\n",
    "lista2=[4, 5, 6]\n",
    "lista3=lista1+lista2\n",
    "print (lista3)\n",
    "\n",
    "tupla1=(1, 2, 3)\n",
    "tupla2=(4, 5, 6)\n",
    "tupla3=tupla1+tupla2\n",
    "print (tupla3)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Podemos crear listas a partir de otras usado los denominados \"slices\" o selección de sublistas mediante índices:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print (\"Lista: \", mi_lista)\n",
    "print (\"Tupla: \", mi_tupla)\n",
    "print(mi_lista[0])  # Primer elemento, 1\n",
    "print(mi_tupla[1])  # Segundo elemento, 2\n",
    "print(mi_lista[0:2])  # Desde el primero hasta el tercero, excluyendo el tercero: 1, 2\n",
    "print(mi_tupla[:3])  # Desde el primero hasta el cuarto, excluyendo el cuarto: 1, 2, 3.0\n",
    "print(mi_lista[-1])  # El último: 7\n",
    "print(mi_tupla[:])  # Desde el primero hasta el último (incluido)\n",
    "print(mi_lista[::2])  # responde al patrón inicio:fin:salto"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Podemos hacer listas de listas"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "bolas = ['roja', 'negra', 'blanca', 'azul']\n",
    "chuches = ['regaliz', 'chicle', 'piruleta']\n",
    "edades = [15, 18, 25, 35]\n",
    "\n",
    "cosas = [bolas, chuches, edades]\n",
    "\n",
    "cosas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Rangos\n",
    "\n",
    "Los rangos son tipos especiales en Python y tienen una sintaxis que ahorra mucho código y es tremendamente intuitiva. Son una manera rápida de generar listas básicas de números.\n",
    "\n",
    "En realidad las instrucciones \"range\" producen lo que en la nomenclatura de Python se denomina **generador** y pueden transformarse en una lista convencional mediante la instrucción de conversión de tipo **list**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# rango del 0 al 5\n",
    "\n",
    "list(range(6))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# En realidad range no producen una lista, produce un objeto range\n",
    "\n",
    "range(6), type(range(6))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# La instrucción list transforma el objeto range en una lista convencional.\n",
    "\n",
    "type(list(range(6)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# igual rango pero las posiciones pares\n",
    "\n",
    "list(range(0, 5, 2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# igual rango pero en sentido decreciente\n",
    "\n",
    "list(range(5, -1, -1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# igual rango pero en orden decreciente y  posiciones impares\n",
    "\n",
    "list(range(5, -1, -2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Listas comprensivas\n",
    "\n",
    "<div class=\"alert alert-info\">\n",
    "Podemos utilizar la \"notación comprensiva\" para definir de forma rápida listas o tuplas:\n",
    "<ul>\n",
    "    <li><font face=\"Courier\"><b>[</b>f[i] <b>for</b> i <b>in</b> secuencia<b>]</b></font></li>\n",
    "<li><font face=\"Courier\"><b>[</b>f[i] <b>for</b> i <b>in</b> secuencia <b>if</b> condicion<b>]</b></font></li>\n",
    "    </ul>\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "l = [1, 2, 3, 4, 5, 6, 7, 8]\n",
    "l2 = [ x**2 for x in l ]\n",
    "\n",
    "print (l2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Cada una de estas construcciones consta de una expresión que determina cómo modificar el elemento de la lista original, seguida de una o varias clausulas for y opcionalmente una o varias clausulas if como vemos en el ejemplo a continuación en el que insertamos una condición adicional para que solo se incluyan los índices correspondientes a números pares:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "l = [1, 2, 3, 4, 5, 6, 7, 8]\n",
    "l2 = [ x**2 for x in l if x % 2 == 0 ]\n",
    "\n",
    "print (l2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Podemos utilizar instrucciones range en la definición de listas comprensivas."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "[i**2 for i in range(1,8)]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A continuación, un ejemplo de anidación de dos bucles:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "l = [0, 1, 2, 3]\n",
    "m = [\"a\", \"b\"]\n",
    "n = [s * v for s in m\n",
    "         for v in l\n",
    "             if v > 0]\n",
    "\n",
    "print (n)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Orden y búsquedas en listas y tuplas\n",
    "\n",
    "Para buscar y ordenar también tenemos varios métodos:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "estudiantes = ['Rosa', 'Antonio', 'Ismael', 'Anabel', 'Miguel', 'Cristina', 'Lucas', 'Miguel']\n",
    "\n",
    "estudiantes.reverse()\n",
    "print(estudiantes)\n",
    "\n",
    "estudiantes.sort(reverse=True)\n",
    "print(estudiantes)\n",
    "\n",
    "estudiantes.sort()\n",
    "print(estudiantes)\n",
    "\n",
    "print (\"Miguel aparece :\", estudiantes.count('Miguel'), \"veces.\")\n",
    "print (\"Miguel aparece en la posición: \", estudiantes.index('Miguel',0,6)) #busca en las posiciones 0..5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Podemos transformar una tupla en lista y viceversa"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tupla = (1, 2, 3, 4) \n",
    "lista=list(tupla) #convertimos en lista\n",
    "print (tupla)\n",
    "print (lista)\n",
    "lista.pop() #como es una lista, es mutable ;-)\n",
    "tupla=tuple(lista) #a tupla de nuevo\n",
    "print (tupla) # hemos modificado una tupla!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Diferencias entre tuplas y listas\n",
    "\n",
    "* Una lista puede ser alterada (es mutable), no así una tupla (es inmutable).\n",
    "* Una tupla puede ser utilizada como clave en un diccionario, no así una lista.\n",
    "* Una tupla consume menos espacio que una lista."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "lista=(1,2,3)\n",
    "lista.pop()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tupla=[1,2,3]\n",
    "tupla.pop()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Introducir e imprimir datos \n",
    "\n",
    "En programación, a veces necesitamos que los datos nos venga del usuario final de la aplicación y nosotros debemos tratar esos datos y orientar al usuario para que sepa que debe escribir o que tipo de dato escribir.\n",
    "\n",
    "Usamos input (o raw_input) donde le podemos poner un mensaje orientativo para ayudar al usuario.\n",
    "\n",
    "Veamos algun ejemplo:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "edad = input(\"Introduce tu edad: \")\n",
    "print (\"Tu edad es: \" + str(edad))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "La salida podemos formatearla con un estilo muy parecido a C"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# Esto imprime \"Hola, Juan!\"\n",
    "\n",
    "nombre = \"Juan\"\n",
    "edad = 18\n",
    "nota = 7.677\n",
    "\n",
    "print (\"Hola, %s! dijiste que tenías %d años?\" % (nombre, 18))\n",
    "print (\"Has sacado un %.2f de nota final\" % nota)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Ejercicios"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Ejercicio 1\n",
    "\n",
    "Solicita al usuario, mediante las correspondientes instrucciones, su nombre y su edad e imprime un mensaje del tipo:<br>\n",
    "Nombre: Antonio López<br>\n",
    "Edad: 53<br>\n",
    "Mensaje a imprimir: Don Antonio López tiene 53 años.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Ejercicio 2\n",
    "\n",
    "¿Qué slice podemos utilizar para obtener la subcadena \"que\" dentro de la cadena\n",
    "\"Espero que te estés enterando de todo\"? ¿Cuál podría servir para obtener la última palabra?\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cadena=\"Espero que te estés enterando de todo\"\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Ejercicio 3\n",
    "\n",
    "Imprime por pantalla todas las potencias de dos menores o iguales que 2048, utilizando una lista comprensiva.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Ejercicio 4\n",
    "\n",
    "Solicita al usuario una lista y ofrece como resultado otra formada por sublistas que contengan cada elemento de la lista original junto con una tupla que incluye los elementos menores a él.\n",
    "\n",
    "<b>Ejemplo:</b> Si se interta [1,2,3] el resultado debería ser"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "[(1,[]),(2,[1]),(3,[1,2])]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Ejercicio 5\n",
    "\n",
    "A partir de dos listas de enteros, 'numeros1' y 'numeros2', crea una lista que contiene aquellos valores de la primera que tambien estan en la segunda e imprimela por pantalla. Es decir, calcula la interseccion de ambas listas.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Ejercicio 6\n",
    "\n",
    "A partir de dos listas de enteros, 'numeros1' y 'numeros2' de igual tamano, generar otra cuyo primer elemento es el producto del primer elemento de las listas 'numeros1' y 'numeros2', y asi sucesivamente.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "numeros1 = [1, 7, 13, 21, 27]\n",
    "numeros2 = [4, 6, 10, 18, 23]\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Ejercicio 7\n",
    "\n",
    "A partir de dos listas de enteros, 'numeros1' y 'numeros2', almacenar en una lista el resultado de multiplicar cada uno de los elementos de 'numeros1' por, a su vez, cada uno de los elementos de 'numeros2'. Es decir, la lista resultante tendra len(numeros1) * len(numeros2) elementos.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "numeros1 = [1, 7, 13, 21, 27]\n",
    "numeros2 = [8, 9, 28, 41, 55, 77]\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "numeros1 = [1, 7, 13, 21, 27, 29, 34, 48, 50, 51, 53, 61, 68, 74, 82, 83, 84, 87, 92, 94]\n",
    "numeros2 = [4, 6, 10, 18, 23, 29, 30, 32, 43, 54, 55, 55, 71, 76, 77, 82, 88, 92, 94, 95]\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Estructuras de control\n",
    "\n",
    "En Python los bloques se delimitan mediante la indentación, utilizando siempre cuatro espacios. Cuando ponemos los dos puntos al final de la primera línea del condicional (que veremos justo a continuación), todo lo que vaya a continuación con un nivel de sangrado superior se considera dentro del condicional. En cuanto escribimos la primera línea con un nivel de sangrado inferior, hemos cerrado el condicional. Si no seguimos esto a rajatabla Python nos dará errores; es una forma de forzar a que el código sea legible.\n",
    "\n",
    "## Condicionales\n",
    "\n",
    "Los condicionales tienen la siguiente forma:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "    if <condición>:\n",
    "        <haz lo que sea>\n",
    "    elif <condición>:\n",
    "        <haz otra cosa>\n",
    "    else:\n",
    "        <haz otra cosa>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### Algunos ejemplos aclaratorios"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x, y = 5, 3\n",
    "print(x,y)\n",
    "if x > y:\n",
    "    print(\"x es mayor que y\")\n",
    "    print(\"x sigue siendo mayor que y\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "if 1 < 0:\n",
    "    print(\"Es falso que \")\n",
    "print(\"eres una buena persona :-)\") "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "if 1 < 0:\n",
    "    print(\"1 es menor que 0\")\n",
    "    print(\"1 sigue siendo menor que 0\") # hay que sangrar correctamente"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(x,y)\n",
    "if x > y:\n",
    "    print(\"x es mayor que y\")\n",
    "else:\n",
    "    print(\"x es menor que y\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(x, y)\n",
    "if x < y:\n",
    "    print(\"x es menor que y\")\n",
    "elif x == y:\n",
    "    print(\"x es igual a y\")\n",
    "else:\n",
    "    print(\"x no es ni menor ni igual que y\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Bucles\n",
    "\n",
    "En Python existen dos tipos de estructuras de control típicas:\n",
    "\n",
    "1. Bucles `while`\n",
    "2. Bucles `for`\n",
    "\n",
    "### while\n",
    "\n",
    "Los bucles `while` repetiran las sentencias anidadas en él mientras se cumpla una condición:\n",
    "\n",
    "    while <condición>:\n",
    "        <cosas que hacer>\n",
    "        \n",
    "Como en el caso de los condicionales, los bloques se separan por indentación sin necesidad de sentencias del tipo `end`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "i = -2\n",
    "while i < 5:\n",
    "    print(i)\n",
    "    i += 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Se puede interrumpir el bucle a la mitad con la sentencia <b>break</b>:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "i = -2\n",
    "while i < 5:\n",
    "    print(i)\n",
    "    i += 1\n",
    "    if i==3:\n",
    "        break"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Un bloque `else` justo después del bucle se ejecuta solamente la primera vez que no se cumple la condición del bucle; por tanto, cuando salimos del bluce a causa de un break no se ejecutará la clausula else:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "i = -2\n",
    "while i < 5:\n",
    "    print(i)\n",
    "    i += 1\n",
    "    if i==3:\n",
    "        break\n",
    "else:\n",
    "    print(\"El bucle ha terminado.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "i = -2\n",
    "while i < 5:\n",
    "    print(i)\n",
    "    i += 1\n",
    "    #if i==3:\n",
    "    #    break\n",
    "else:\n",
    "    print(\"El bucle ha terminado.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### for\n",
    "\n",
    "El otro bucle en Python es el bucle `for` y funciona de manera que puede resultar chocante al principio. La idea es recorrer un conjunto de elementos:\n",
    "\n",
    "    for <elemento> in <objeto iterable>:\n",
    "        <haz lo que sea...>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for i in (1,2,3,4,5):\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for nombre in \"Juanlu\", \"Siro\", \"Carlos\":\n",
    "    print(nombre)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for i in range(3):\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for j in range(2, 5):\n",
    "    print(j)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for nombre in \"Juanlu\", \"Siro\", \"Carlos\":\n",
    "    if nombre == \"Carlos\":\n",
    "        break\n",
    "    print(nombre)\n",
    "else:\n",
    "    print(\"¿Carlos excluido?\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Ejercicios\n",
    "\n",
    "#### Ejercicio 8\n",
    "\n",
    "Imprime por pantalla todas las potencias de dos menores o iguales que 2048, utilizando un bucle while\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Ejercicio 9\n",
    "\n",
    "Lee valores del usuario hasta que teclee un numero par, utilizando un bucle while\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Ejercicio 10\n",
    "\n",
    "Imprime por pantalla las primeras 15 potencias de dos\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Ejercicio11\n",
    "\n",
    "Lee una cadena de texto del usuario y para cada letra indica si es una vocal o una consonante\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Ejercicio 12\n",
    "\n",
    "Para cada una de las palabras almacenadas en una cadena, imprimir por pantalla el índice y la cadena en si e indicar si la palabra es demasiado corta (cinco o menos caracteres) o larga (mas de cinco caracteres)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Ejercicio 13\n",
    "\n",
    "Recibe una lista de enteros y calcula la media aritmetica\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "enteros = [1, 5, 9, 12, 13, 19, 23, 27, 29, 30, 57, 59, 67, 83, 92, 98, 100]\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Ejercicio 14\n",
    "\n",
    "Lee una cadena de texto del usuario e imprime por pantalla un mensaje si y sólo si contiene todas las vocales"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Ejercicio 15\n",
    "\n",
    "Calcula el decimal número 20 del número e"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Ejercicio 16\n",
    "Calcula los 1000 primeros números primos"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
