¿Qué es programar?

Un programa de ordenador es una serie de instrucciones que le dicen a la máquina qué tiene que hacer. Las máquinas no entienden nuestro lenguaje, por lo que tenemos que aprender un lenguaje para poder comunicarnos con ellas y darles órdenes. Hay muchísimos lenguajes de programación hoy en día, cada lenguaje se usa para hacer un tipo de programa. Por ejemplo, si quieres hacer una página web puedes usar HTML, CSS y Javascript, si quieres hacer un programa para consultar una base de datos puedes usar SQL. En el caso de Python, es un lenguaje usado para muchas cosas: desde hacer cálculos científicos hasta programación web, pasando por robótica, seguridad, ciencia de datos, física y muchísimas cosas más. Además, Python es muy sencillo de entender y programar, ya que simplifica muchas tareas que en otros lenguajes como C son muy tediosas. Por eso, es ideal para entender los conceptos básicos de programación y para iniciarse en este mundillo.

Instalación

Linux

Python viene instalado por defecto en todas las distribuciones Linux. En Ubuntu, la versión que viene instalada es python2 y en otras distribuciones como Arch Linux, la versión es python3. Lo recomendable si vas a iniciarte en Python es que empieces directamente por python3. Para comprobar la versión que tenemos instalada ejecutamos el siguiente comando en consola:

[[email protected] ~]$ python -V
Python 3.6.0

En mi caso, tengo la versión 3.6 instalada. En el caso de que tengas una versión de python2, instala la versión 3 usando el siguiente comando:

  • Ubuntu: sudo apt-get install python3
  • CentOS: sudo yum install python3

Windows y Mac OS

Para instalar Python en otros sistemas operativos, descarga el instalador de la página oficial de python.

La consola de Python

Python es un lenguaje de programación interpretado, ¿qué quiere decir esto? que interpreta cada instrucción que hemos escrito en nuestro programa a la hora de ejecutar. Otros lenguajes, como C o Java son compilados, por lo que necesitamos generar un ejecutable (los famosos .exe, para que nos entendamos) para poder ejecutarlos. El hecho de que Python sea interpretado nos permite tener una consola donde introducir comandos sin tener que crear un programa y compilarlo. Podemos ejecutar esta consola simplemente ejecutando el siguiente comando:

[[email protected] ~]$ python
Python 3.6.0 (default, Dec 24 2016, 08:03:08) 
[GCC 6.2.1 20160830] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

También tenemos disponible la consola ipython, una consola de Python que resalta el código que escribimos y autocompleta si pulsamos el tabulador. Para ejecutarla simplemente tenemos que poner el siguiente comando en consola:

[[email protected] ~]$ ipython
Python 3.6.0 (default, Dec 24 2016, 08:03:08) 
Type "copyright", "credits" or "license" for more information.

IPython 5.1.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]:

Tanto el >>> de la consola de Python como el In [1]: de la consola de iPython son conocidos como el prompt, donde podemos escribir instrucciones para que el intérprete las ejecute.

Jupyter

Un notebook de Jupyter es una especie de consola de Python que nos permite poder escribir comentarios en Markdown. Es muy útil para poder hacer tutoriales como éste, ya que dispones de la explicación y el código para ejecutar y probar en el mismo sitio. Vamos a empezar a usar la consola de python incluida en jupyter para hacer las primeras pruebas. Para instalar Jupyter podemos usar tanto pip como anaconda:

[[email protected] ~]$ sudo pip3 install --upgrade pip && sudo pip3 install jupyter

Hola mundo!

Una vez tenemos Python instalado y hemos elegido nuestro intérprete favorito, vamos a empezar a programar. El primer programa que se suele hacer en todos los lenguajes de programación es conocido como el hola mundo. En otros lenguajes como C, tendríamos que hacer varias líneas de código y, después, compilar nuestro programa para poder ejecutarlo, en cambio, en Python lo podemos ejecutar en una sola línea!

In [1]:
print("Hola mundo!")
Hola mundo!

Ahora imagina que quieres hacer un programa para saludar a tu amiga Marta, ¿cómo lo harías? De primeras, podrías hacer lo siguiente:

In [2]:
print("Hola Marta!")
Hola Marta!

Así, tendríamos un programa para saludar a cualquier Marta del mundo, pero, ¿y si quisiéramos un programa para poder saludar a cualquier persona? Para poder llevar esto a cabo necesitamos introducir un concepto de programación básico: las variables.

Variables

Una variable en programación describe un lugar donde guardar información, que puede ser diferente en cada ejecución. En nuestro caso, queremos saludar al usuario que ejecute nuestro programa, pero no sabemos su nombre a priori y no lo sabremos hasta la ejecución, por tanto, necesitamos reservar un espacio para poder guardar ahí el nombre del usuario durante la ejecución de nuestro programa.

Hay muchos tipos de variables:

  • números enteros (int)
  • números reales (float o double)
  • caracteres (char) y cadenas de caracteres (string)
  • booleanos (bool), estos últimos sólo pueden tomar dos valores: verdadero (True) o falso (False).

En otros lenguajes de programación, como C, necesitamos indicar el tipo que tiene cada variable que declaramos. En cambio, en python no es necesario ya que el propio intérprete lo infiere por sí mismo.

Una vez hemos aprendido el concepto de variable, ya sí podemos hacer nuestro programa para saludar a cualquier persona.

In [4]:
nombre = input("¿Cómo te llamas? ")
print("Hola ", nombre,"!")
¿Cómo te llamas? Marta
Hola  Marta !

Operando con variables

En Python podemos hacer operaciones sobre las variables que tenemos de forma muy sencilla. A modo de resumen, las principales operaciones en python son:

Símbolo Operación
+ suma
- resta
* multiplicación
/ división

Estos operadores se pueden usar con cualquier tipo de variable, tanto números como letras. A continuación, te muestro varios ejemplos.

Podemos concatenar dos palabras usando el operador +.

In [5]:
nombre1 = "Marta"
nombre2 = "María"
suma_nombres = nombre1 + " y " + nombre2
print(suma_nombres)
Marta y María

También podemos multiplicar una palabra por un número usando el operador *.

In [6]:
num1 = 5
mult_letra_num = nombre1 * 5
print(mult_letra_num)
MartaMartaMartaMartaMarta

Y por último, también podemos hacer operaciones numéricas. En las operaciones numéricas Python respeta el orden de los operadores: primero se realizan las multiplicaciones y divisiones y, después, las sumas y restas. Si queremos cambiar este orden simplemente tenemos que usar paréntesis.

In [7]:
num2 = 6
operacion1 = num1 + num2 * 2
print(operacion1)
operacion2 = (num1 + num2) * 2
print(operacion2)
17
22

En el primer caso hemos realizado la operación

$$5 + (6 * 2) = 5 + 12 = 17$$

y en el segundo, en cambio

$$ (5 + 6) * 2 = 11 * 2 = 22$$

Ejercicio:

Haz un pequeño programa que le pida al usuario introducir dos números ($x_1$ y $x_2$), calcule la siguiente operación y muestre el resultado de la misma ($x$):

$$ x = \frac{20 * x_1 - x_2}{x_2 + 3} $$

Si intentas operar con el resultado de la función input obtendrás un error que te informa que no se pueden restar dos datos de tipo str. Usa la función int para convertir los datos introducidos por teclado a datos numéricos.

Librería math

Una librería es un conjunto de operaciones relacionadas entre sí, guardadas en una especie de "paquete". En este caso, vamos a hablar de la librería math que tiene operaciones matemáticas más avanzadas tales como la raíz cuadrada.

Para poder usar esta librería debemos importarla a nuestro programa. Esto se hace usando la instrucción import:

In [8]:
import math

print(math.sqrt(4))
2.0

Usando sólo la instrucción import debemos preceder la instrucción que queremos del nombre de la librería. Si este nombre es muy largo, podemos importar la librería usando un alias:

In [9]:
import math as m

print(m.sqrt(4))
2.0

Ahora bien, si sólo vamos a usar unas operaciones concretas de una librería, podemos especificar cuáles son y así no tener que usar el nombre de la librería para poder utilizarlas.

In [10]:
from math import sqrt

print(m.sqrt(4))
2.0

Esta librería tiene muchas más operaciones que puedes consultar en la documentación oficial

Estructuras de control

Hasta ahora, nuestros programas se basan en una serie de instrucciones que se ejecutan una detrás de otra. Esto limita mucho los programas que podemos hacer, ya que no nos permite controlar el flujo de ejecución (control flow) de nuestro programa. A continuación vamos a ver una serie de instrucciones especiales que nos permiten hacer precisamente eso.

if

Imagina que estás operando con raíces cuadradas, como sabrás la raíz cuadrada de un número es negativa, y quieres evitar hacer la raíz cuadrada si el número introducido por el usuario es negativo.

In [11]:
num = int(input("Introduce un número: "))
raiz = sqrt(num)
Introduce un número: -4
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-11-1bfe41810136> in <module>()
      1 num = int(input("Introduce un número: "))
----> 2 raiz = sqrt(num)

ValueError: math domain error

¿Qué podemos hacer para que no ocurra esto? Controlar con un if la condición de que el número sea positivo para hacer la raíz cuadrada y avisar al usuario en caso contrario:

In [12]:
num = int(input("Introduce un número: "))
if num > 0:
    raiz = sqrt(num)
else:
    print("No puedo hacer la raíz de un número negativo!")
Introduce un número: -4
No puedo hacer la raíz de un número negativo!

Si quisiéramos controlar una condición más, usaríamos la instrucción elif, que en otros lenguajes como C es conocida como else if:

In [13]:
if num > 0:
    raiz = sqrt(num)
elif num == 0:
    print("Para qué quieres saber eso jaja saludos")
else:
    print("No puedo hacer la raíz de un número negativo!")
No puedo hacer la raíz de un número negativo!

Ejercicio

Haz un programa que le pida al usuario un número (de ninjas). Si dicho número es menor que 50 y es par, el programa imprimirá "puedo con ellos!", en caso contrario imprimirá "no me vendría mal una ayudita..."

Nota: para saber si un número es par o no debes usar el operador $\%$ y para saber si dos condiciones se cuplen a la vez, el operador lógico and

while

En el ejemplo anterior le decíamos al usuario que no podíamos hacer la raíz negativa de un número pero, ¿cómo haríamos para, en vez de darle este mensaje, volver a pedirle un número una y otra vez hasta que fuese negativo? Necesitamos ejecutar el mismo código hasta que se dé la condición que buscamos: que el usuario introduzca un número positivo.

Esto podemos hacerlo usando un bucle while!

In [14]:
num = int(input("Introduce un número: "))

while (num < 0):
    num = int(input("Introduce un número: "))

raiz = sqrt(num)
print(raiz)
Introduce un número: -4
Introduce un número: 4
2.0

Ejercicio

Haz un bucle while que imprima todos los números desde el 0 hasta un número que introduzca el usuario. Si el número que introduce es negativo puedes tomar dos decisiones: pedirle que introduzca un número positivo o contar hacia atrás, tú eliges!

for

En lenguajes de programación como C o Java, un bucle for sirve para recorrer una secuencia de números, de la siguiente forma:

for (int i=0; i<maximo_numero; i++)

Donde maximo_numero es una variable previamente definida.

Hay también otro tipo de bucles for denominados forEach en Java que sirven para iterar sobre los elementos de cualquier estructura de datos (más adelante veremos lo que es). En Python, los bucles for tienen esta función: iterar sobre una serie de elementos.

Para iterar sobre una serie de números, debemos generar dicha serie usando la función range(). Así, el ejercicio anteriormente pleanteado para resolverse con un bucle while sería:

In [15]:
for i in range(num):
    print(i)
0
1
2
3

¿Qué es eso de la función range()? Sirve para generar una secuencia de números. Puedes consultar más sobre esta función en la documentación de Python. En Python 2, existían tanto range como xrange aunque en Python 3, range hace lo mismo que hacía xrange en Python 2.

Ejercicio

Genera con range los números pares del 0 al 10, ambos inclusive. ¿Qué cambiarías para generar del 2 al 10?

break

La sentencia break sirve para detener un bucle antes de que llegue al final (en un bucle for) o antes de que la condición sea falsa (en un bucle while).

Los bucles (for y while) pueden tener una sentencia else como los if. Esta sentencia else se ejecuta si el bucle no ha terminado por un break y nos puede servir para controlar cuando un bucle termina o no debido a un break de forma sencilla.

El código siguiente refleja muy bien esto: para saber si un número $n$ es primo calculamos su módulo entre todos los números en el intervalo $[2,n)$ y, en el momento en el que uno de estos módulos sea igual a $0$, sabremos que $n$ no es primo.

In [16]:
for n in range(2,10):
    for x in range(2, n):
        if n % x == 0:
            print(n, " = ", x, " * ", n//x)
            break
    else:
        print(n, " es primo!")
2  es primo!
3  es primo!
4  =  2  *  2
5  es primo!
6  =  2  *  3
7  es primo!
8  =  2  *  4
9  =  3  *  3

Cuando $n \% x = 0$, dejamos de hacer módulos con $n$ pues ya sabemos que no es primo. Por tanto, nos salimos del bucle con un break. Al salirnos con el break, no entramos en el else sino que volvemos al bucle inicial. En cambio, no hemos encontrado ningún $x$ tal que $n \% x = 0$, ejecutamos la condición else para decir que $n$ es primo.

Ejercicio

¿Cuál es la diferencia entre la sentencia break y la sentencia continue?

Pista: consúltalo en la documentación de Python.

Estructuras de datos

Por ahora sólo hemos estudiado variables en las que podemos guardar un único valor: un número, una letra, una frase... ¿No te da la impresión de que esto se queda algo corto? Sí, y probablemente no eres la única persona que lo ha pensado. Las estructuras de datos son variables compuestas, esto quiere decir que en ellas podemos almacenar muchos datos. Hay estructuras de datos de todo tipo, en python tenemos las siguientes:

  • Listas
  • Tuplas
  • Conjuntos
  • Diccionarios

Listas

Imagina que quieres guardar en una variable los nombres de tus mejores amigos. Una muy buena opción para hacerlo es una lista. Al igual que en la vida real hacemos listas como lista de cosas por hacer, lista para la compra, lista de propósitos de año nuevo, etc. en Python también podemos hacerlas usando esta estructura de datos.

Con las listas, podemos guardar en un mismo sitio variables relacionadas entre sí. Esto nos permite poder aplicar operaciones sobre todas ellas sin tener que repetir código.

Para declarar una lista, usaremos los [].

In [17]:
mis_amigos = ['Paloma', 'Paula', 'Teresa', 'Marina', 'Braulio']
print(mis_amigos)
['Paloma', 'Paula', 'Teresa', 'Marina', 'Braulio']

Al imprimir la lista vemos los diferentes elementos que contiene. Pero, ¿y si queremos acceder a sólo uno de los elementos? En ese caso, necesitarás acceder mediante índices. Cada elemento de la lista tiene un número asociado con su posición dentro de la misma:

Elemento Posición
Paloma 0
Paula 1
Teresa 2
Marina 3
Braulio 4

así, si por ejemplo queremos únicamente mostrar a nuestro mejor amigo, accederemos a él mediante el índice 0:

In [18]:
mis_amigos[0]
Out[18]:
'Paloma'

Si intentamos acceder a un índice superior al último de todos, 4, obtendremos un error:

In [19]:
mis_amigos[5]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-19-098c31af022d> in <module>()
----> 1 mis_amigos[5]

IndexError: list index out of range

Entonces, uno podría pensar que está obligado a conocer la longitud de la lista si quiere acceder al último elemento pero nada más lejos de la realidad! En python, también existen los índices inversos que nos permiten acceder a los elementos de la lista al revés:

Elemento Posición
Paloma -5
Paula -4
Teresa -3
Marina -2
Braulio -1

Por lo que para acceder al último elemento de nuestra lista sólo tendríamos que usar el índice -1:

In [20]:
mis_amigos[-1]
Out[20]:
'Braulio'

Otra cosa que nos podemos hacer usando índices es quedarnos con una sublista. Por ejemplo, si quisiéramos quedarnos únicamente con un top 3 de amigos guays podríamos hacerlo usando el operador :

In [21]:
mis_amigos[0:3]
Out[21]:
['Paloma', 'Paula', 'Teresa']

Pero si queremos quedarnos con los tres primeros, podemos simplemente hacerlo de la siguiente forma:

In [22]:
mis_amigos[:3]
Out[22]:
['Paloma', 'Paula', 'Teresa']

¿Y si queremos saber el resto? Simplemente, lo hacemos al revés!

In [23]:
mis_amigos[3:]
Out[23]:
['Marina', 'Braulio']

Ejercicio:

Haz una lista de la compra e imprime los siguientes elementos:

  • Penúltimo elemento
  • Del segundo al cuarto elemento
  • Los tres últimos
  • Todos!

Por último, elimina el tercer elemento de la lista usando la sentencia del

Iterando sobre una lista

Con los bucles podemos iterar sobre los valores de una lista. Típicamente, un programador C iteraría sobre una lista de la siguiente forma:

In [24]:
for i in range(len(mis_amigos)):
    print(mis_amigos[i])
Paloma
Paula
Teresa
Marina
Braulio

Ahora bien, en Python existe una forma mucho más cómoda de iterar sobre los valores de una lista sin tener que estar pendiente de un índice i:

In [25]:
for amigo in mis_amigos:
    print(amigo)
Paloma
Paula
Teresa
Marina
Braulio

En Python también existe lo que se llama list comprehesions, que son una forma mucho más sencilla y fácil de leer para crear listas. Por ejemplo, si queremos hacer una lista con las potencias de 2, podríamos hacerlo de la siguiente forma:

In [26]:
potencias = []
for x in range(10):
    potencias.append(2**x)

print(potencias)
[1, 2, 4, 8, 16, 32, 64, 128, 256, 512]

Tendríamos nuestra lista de potencias de 2 en tres líneas, pero con los list comprehesions podemos hacerlo en una única línea:

In [27]:
potencias = [x**2 for x in range(10)]
print(potencias)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Ejercicio

Crea una lista con todos los números pares del 0 al 10 en una única línea.

Listas anidadas

Seguramente te habrás preguntado si se puede hacer una lista cuyos elementos sean listas, y la respuesta es ¡sí!. Esta representación de listas anidadas se suele usar para representar matrices. Por ejemplo, si queremos representar la siguiente matriz en Python:

$$ M_{2 \times 3} = \left ( \begin{matrix} 1 & 2 & 3 \\ 2 & 3 & 4 \end{matrix} \right)$$

Lo haríamos de la siguiente forma:

In [28]:
M = [[j for j in range(i, i+3)] for i in range(1,3)]
M
Out[28]:
[[1, 2, 3], [2, 3, 4]]

Ejercicio

Crea la siguiente matriz en una línea:

$$ M_{2 \times 3} = \left ( \begin{matrix} 1 & 2 & 3 \\ 4 & 5 & 6 \end{matrix} \right)$$

Tuplas

Imagina que deseas guardar tanto los nombres de tus mejores amigos como su edad. De primeras podrías pensar en hacer dos listas, de la siguiente forma:

índice 0 1 2 3 4
nombres Paloma Paula Teresa Marina Braulio
edades 25 20 19 19 21

De tal forma que para saber la edad de Paloma (primer elemento de la lista nombres) tendríamos que mirar el primer elemento de la lista edades. Pero, ¿y si te dijera que en Python podríamos guardar en una misma variable la edad y el nombre de una persona? Se puede! Con las llamadas tuplas.

Una tupla es una serie de valores separados por comas.

In [29]:
tupla_ejemplo = 5, 'perro', 3.6
print(tupla_ejemplo)
(5, 'perro', 3.6)

Por tanto, para guardar en una lista tanto el nombre como la edad de nuestros amigos podríamos hacerlo de la siguiente forma:

In [30]:
amigos_edades = [('Paloma', 25), ('Paula', 20), ('Teresa', 19), ('Marina', 19), ('Braulio', 21)]
print(amigos_edades)
[('Paloma', 25), ('Paula', 20), ('Teresa', 19), ('Marina', 19), ('Braulio', 21)]

Los valores de las tuplas también tienen índices, por tanto, en nuestro caso el nombre tendría el índice 0 y la edad el índice 1. Por tanto, si queremos acceder a la edad de Paloma tenemos que usar el operador [] dos veces: una para acceder al elemento de la lista que queremos y otra para acceder al elemento de la tupla que queremos.

In [31]:
amigos_edades[0][1]
Out[31]:
25

Si queremos crear dos variables separadas para guardar el nombre y la edad de nuestro mejor amigo, podemos hacerlo en una sola línea!

In [32]:
nombre, edad = amigos_edades[0]

print(nombre)
print(edad)
Paloma
25

Cuidado! Si por casualidad un amigo cumpliese un año más no podríamos ponerlo en la tupla, debido a que las tuplas no pueden modificarse.

In [33]:
amigos_edades[0][1] += 1
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-33-962ba5e9fbd9> in <module>()
----> 1 amigos_edades[0][1] += 1

TypeError: 'tuple' object does not support item assignment

Ejercicio:

Vuelve a hacer la lista de la compra que hiciste en el último ejercicio, pero esta vez guarda cada elemento de la lista de la compra junto con su precio. Después, imprime los siguientes elementos:

  • El precio del tercer elemento.
  • El nombre del último elemento.
  • Tanto el nombre como el precio del primer elemento.

Cojuntos

Un conjunto es una lista de elementos ordenados y en la que no hay elementos repetidos. Se definen con el operador {. Sus operadores básicos son eliminar elementos repetidos, consultar si un elemento está en el conjunto o no y, por supuesto, operaciones típicas de los conjuntos como la unión, la intersección, la diferencia...

¿Qué ventajas puede darte usar un conjunto en lugar de una lista? Al estar ordenados, es mucho más rápido encontrar un elemento aunque esto también hace que insertar nuevos elementos sea más costoso.

Podemos crear un conjunto a partir de una lista:

In [34]:
mi_lista = [5,4,6,3,7,5,1,9,3]
print(mi_lista)
mi_conjunto = set(mi_lista)
print(mi_conjunto)
[5, 4, 6, 3, 7, 5, 1, 9, 3]
{1, 3, 4, 5, 6, 7, 9}

Además, podemos hacer las operaciones típicas sobre conjuntos.

In [35]:
A = {1,2,4,5,6,7}
B = {2,3,5,6,8,9}

Elementos de A que no están en B (diferencia):

In [36]:
A - B
Out[36]:
{1, 4, 7}

Elementos que están o bien en A o bien en B (unión):

In [38]:
A | B
Out[38]:
{1, 2, 3, 4, 5, 6, 7, 8, 9}

Elementos que están tanto en A como en B (intersección):

In [39]:
A & B
Out[39]:
{2, 5, 6}

Elementos que están en A o en B pero no en ambos (diferencia simétrica):

In [40]:
A ^ B
Out[40]:
{1, 3, 4, 7, 8, 9}

¿Podríamos hacer un conjunto de listas?

In [1]:
{[1,2,3],[4,5,6]}
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-1-190d408ffc9a> in <module>()
----> 1 {[1,2,3],[4,5,6]}

TypeError: unhashable type: 'list'

¡No! Esto es debido a que los elementos de los conjuntos deben ser hashables. Tal y como se explica en la documentación, un objeto es hashable si su clase define la función __hash__(), que calcula un entero para caracterizar a un objeto, por lo que objetos con el mismo valor deben tener el mismo entero hash, y la función __eq__(), que sirve para comparar objetos.

Las estructuras de datos que pueden cambiar su valor, como las listas o los diccionarios, no son hashables y, por lo tanto, no pueden ser elementos de un conjunto.

Iterando sobre conjuntos

Al igual que con las listas, también es posible iterar sobre conjuntos y hacer set comprehesions:

In [35]:
{x for x in 'abracadabra' if x not in 'abc'}
Out[35]:
{'d', 'r'}
In [36]:
for c in mi_conjunto:
    print(c)
1
3
4
5
6
7
9

Ejercicio

¿Es buena idea usar la función set para eliminar los elementos repetidos de una lista?

Un último detalle sobre conjuntos: para crear un conjunto vacío usamos set() ya que usar {} creará un diccionario vacío.

Diccionarios

A diferencia de las estructuras de datos que hemos visto hasta ahora, los diccionarios no se indexan por números sino por claves (keys). Cada entrada de nuestro diccionario está formada por dos valores distintos: la clave y el valor. La clave nos sirve para acceder al elemento (valor) de forma rápida. Debido a que las claves sirven para identificar a cada elemento,deben ser únicas: si introduces un nuevo elemento en el diccionario con clave repetida, se sobreescribirá el elemento anterior así que ¡mucho cuidado!

Vamos a ver un pequeño ejemplo de uso de los diccionarios para que nos quede más claro. Volvamos al ejemplo anterior sobre nuestros amigos y su edad.

In [41]:
mis_amigos = {'Paloma':25, 'Paula':20, 'Teresa':19, 'Marina':19, 
              'Braulio':21}
print(mis_amigos)
{'Paloma': 25, 'Paula': 20, 'Teresa': 19, 'Marina': 19, 'Braulio': 21}

Para obtener la edad de Paloma, antes teníamos que estar mirando qué índice tenía en la lista, en cambio, ahora lo tenemos mucho más sencillo:

In [42]:
print(mis_amigos['Paloma'])
25

Si queremos saber los nombres de cada uno de nuestros amigos podemos listar las claves:

In [43]:
list(mis_amigos.keys())
Out[43]:
['Paloma', 'Paula', 'Teresa', 'Marina', 'Braulio']

Y también podemos ver si hemos incluido a un amigo o no en nuestro diccionario:

In [44]:
'Marta' in mis_amigos
Out[44]:
False

La función dict nos permite hacer diccionarios directamente desde Tuplas de la siguiente forma:

In [46]:
dict([('Paloma',25), ('Paula',20), ('Teresa',19), ('Marina', 19), 
      ('Braulio', 21)])
Out[46]:
{'Braulio': 21, 'Marina': 19, 'Paloma': 25, 'Paula': 20, 'Teresa': 19}

Y cuando las keys son simples string también es posible definir un diccionario de la siguiente forma:

In [47]:
dict(Paloma=25, Paula=20, Teresa=19, Marina=19, Braulio=21)
Out[47]:
{'Braulio': 21, 'Marina': 19, 'Paloma': 25, 'Paula': 20, 'Teresa': 19}

Iterando sobre diccionarios

Es posible crear diccionarios en una sola línea, usando las dict comprehesions. En el siguiente ejemplo, cada clave almacena su valor al cuadrado:

In [42]:
{x: x**2 for x in (2,4,6)}
Out[42]:
{2: 4, 4: 16, 6: 36}

Aunque también es posible iterar sobre diccionarios usando bucles for. Para ello, usamos la función items:

In [48]:
for nombre, edad in mis_amigos.items():
    print(nombre, edad)
Paloma 25
Paula 20
Teresa 19
Marina 19
Braulio 21

Cuando iteramos sobre una lista o un conjunto, podemos usar la función enumerate para obtener la posición y el elemento de la misma forma:

In [49]:
for posicion, elemento in enumerate(['tic', 'tac', 'toe']):
    print(posicion, elemento)
0 tic
1 tac
2 toe

Por último, si queremos iterar sobre dos listas o conjuntos a la vez (del mismo tamaño), podemos hacerlo usando la función zip:

In [50]:
questions = ['name', 'quest', 'favourite color']
answers = ['lancelot', 'the holy grail', 'blue']

for q, a in zip(questions, answers):
    print("What is your {}? It is {}.".format(q,a))
What is your name? It is lancelot.
What is your quest? It is the holy grail.
What is your favourite color? It is blue.

En este ejemplo también vemos el uso de la función format, que sirve para meter valores en un string. No sólo se puede usar para imprimir por pantalla sino para guardar valores en una variable y mucho más!

Ejercicio

Usando la tupla que creaste en el ejercicio sobre tuplas, crea un diccionario de tu lista de la compra. Una vez tengas el diccionario creado:

  • Imprime todos los elementos que vayas a comprar creando la siguiente frase con la función format: "he comprado __ y me ha costado __".
  • Consulta si has añadido un determinado elemento (por ejemplo un cartón de leche) a la lista de la compra
  • Elimina un elemento usando la función del