# Caso práctico: Agenda

## <mark style="color:blue;">1. Implementando la agenda digital y los contactos</mark>

Lo primero que debemos hacer para implementar nuestra agenda digital es seleccionar la estructura de datos que va a almacenar los contactos de la misma.

Crea un diccionario que represente la agenda digital. Dentro de ese diccionario, crea otro diccionario por cada uno de los contactos que quieras almacenar en ella. Los contactos deben tener, al menos, los siguientes atributos: Nombre, dirección, email y teléfono.

{% hint style="info" %}
**Pista:** Utiliza algo característico de cada contacto como clave del primer diccionario, por ejemplo, su nombre completo.
{% endhint %}

```python
agenda_digital = {
    # Primer contacto de la agenda
    "Alex Fernandez": {
        "Dirección": "Calle Lorem Ipsum 57", 
        "Email": "lorem@ipsum.com", 
        "Teléfono": "696 66 99 66", 
    }, # Tienen que separarse por comas
    # Segundo contacto de la agenda
    "Fernando Moreno": {
        "Dirección": "Calle Ipsum Lorem 89", 
        "Email": "ipsum@lorem.com", 
        "Teléfono": "649 55 44 33", 
    }
}

agenda_digital["Alex Fernandez"]
{'Dirección': 'Calle Lorem Ipsum 57',
 'Email': 'lorem@ipsum.com',
 'Teléfono': '696 66 99 66'}
 
agenda_digital["Fernando Moreno"]
{'Dirección': 'Calle Ipsum Lorem 89',
 'Email': 'ipsum@lorem.com',
 'Teléfono': '649 55 44 33'}
```

## <mark style="color:blue;">2. Guarda la agenda digital en un fichero en disco</mark>

Una vez que hemos implementado nuestra agenda digital en Python, necesitamos establecer un mecanismo para almacenar esta información en disco. De esta manera, la información que almacenemos en la agenda no se perderá cuando finalice la ejecución del programa.

Implementa una función en Python que permita escribir en disco la agenda digital que has representado en el apartado anterior como un diccionario.

{% hint style="info" %}
**Pista:** Entre las funciones por defecto que veíamos en secciones anteriores, existe una función `open()` que nos permite realizar operaciones de lectura y escritura de ficheros.
{% endhint %}

```python
agenda_fichero = open("agenda_digital", "w")
```

{% hint style="info" %}
**Pista 2**: Una vez que hayas leído el fichero en el que vas a escribir tu agenda digital utilizando la función `open()` y se lo hayas asignado a una variable `agenda_fichero`, utiliza el método `agenda_fichero.write()` para escribir el diccionario en el fichero. Por el momento no hace falta que comprendas que son los métodos, lo veremos más adelante en el curso.
{% endhint %}

```python
# Esta sentencia escribe el diccionario en el fichero
agenda_fichero.write(str(agenda_digital))

# Esta sentencia cierra el fichero que has abierto con la funcion open()
agenda_fichero.close()
```

{% hint style="info" %}
**Pista 3**: Recuerda que debes escribir una función, te recomiendo que tu función tenga una definición similar a la siguiente:
{% endhint %}

```python
def escribir_agenda(nombre_agenda, agenda_digital):
    <sentencias que escriben la agenda digital en disco>
```

```python
def escribir_agenda(nombre_agenda, agenda_digital):
    """Escribe la agenda en un fichero de texto
    Parámetros posicionales
    nombre_agenda -- str que representa el nombre de la agenda en disco
    agenda_digital -- dict que representa la agenda digital y los contactos
    """
    # Guarda la agenda en disco con la función open()
    agenda_fichero = open(nombre_agenda, "w")
    # Esta sentencia escribe el diccionario en el fichero
    agenda_fichero.write(str(agenda_digital))
    # Esta sentencia cierra el fichero que has abierto con la funcion open()
    agenda_fichero.close()
```

## <mark style="color:blue;">3. Lee la agenda digital de un fichero en disco</mark>

Ahora que ya hemos definido como va a ser nuestra agenda digital y hemos implementado una función para escribirla en disco y no perder la información que guardamos en ella, lo siguiente que debemos hacer es escribir otra función que nos permita leer ese fichero cada vez que queramos consultar algún contacto.

Implementa una función en Python que nos permita leer el fichero en el que has escrito la agenda digital y has almacenado en disco en el apartado anterior.

{% hint style="info" %}
**Pista:** La función por defecto `open()` nos permite proporcionarle varios argumentos, entre los que se encuentra uno que nos permite leer un fichero en modo lectura
{% endhint %}

```python
agenda_digital_lectura = open("agenda_digital", "r")
```

{% hint style="info" %}
**Pista 2**: Una vez que hayas leído el fichero en el que se encuentra tu agenda digital utilizando la función `open()` y se lo hayas asignado a una variable `agenda_digital_lectura`, utiliza el método `agenda_digital_lectura.readlines()` para leer todas las líneas del fichero. Por el momento no hace falta que comprendas que son los métodos, lo veremos más adelante en el curso.
{% endhint %}

{% code overflow="wrap" %}

```python
# Esta sentencia lee todas las líneas del fichero y las asigna a la variable agenda_digital
agenda_digital = agenda_digital_lectura.readlines()

# Esta sentencia cierra el fichero que has abierto con la función open()
agenda_digital_lectura.close()
```

{% endcode %}

Comprueba la información que se encuentra en la variable `agenda_digital`.

* ¿Qué tipo de dato es?
* ¿En qué posición se encuentra el diccionario que representa tu agenda?
* ¿Qué tipo de dato es este diccionario? ¿Puedes acceder a sus claves?

{% code overflow="wrap" %}

```python
agenda_digital # Nos devuelve una lista
["{'Alex Fernandez': {'Dirección': 'Calle Lorem Ipsum 57', 'Email': 'lorem@ipsum.com', 'Teléfono': '696 66 99 66'}, 'Fernando Moreno': {'Dirección': 'Calle Ipsum Lorem 89', 'Email': 'ipsum@lorem.com', 'Teléfono': '649 55 44 33'}}"]

agenda_digital[0] # Nos devuelve el primer diccionario
"{'Alex Fernandez': {'Dirección': 'Calle Lorem Ipsum 57', 'Email': 'lorem@ipsum.com', 'Teléfono': '696 66 99 66'}, 'Fernando Moreno': {'Dirección': 'Calle Ipsum Lorem 89', 'Email': 'ipsum@lorem.com', 'Teléfono': '649 55 44 33'}}"

type(agenda_digital[0])
str

dict(agenda_digital[0]) # Al intentar hacer un casting a dict nos devuelve un error
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[114], line 1
----> 1 dict(agenda_digital[0])

ValueError: dictionary update sequence element #0 has length 1; 2 is required
```

{% endcode %}

{% hint style="info" %}
**Pista 3**: Como habrás podido observar, el diccionario que representa nuestra agenda digital, cuando lo hemos leído con la función `open()` a partir del fichero en el que se encontraba almacenado viene representado con tipo `str`. Conviértelo de nuevo en un diccionario, para ello, échale un ojo a la función por defecto de Python `eval()`.
{% endhint %}

```python
eval(agenda_digital[0])
{'Alex Fernandez': {'Dirección': 'Calle Lorem Ipsum 57',
  'Email': 'lorem@ipsum.com',
  'Teléfono': '696 66 99 66'},
 'Fernando Moreno': {'Dirección': 'Calle Ipsum Lorem 89',
  'Email': 'ipsum@lorem.com',
  'Teléfono': '649 55 44 33'}}
  
type(eval(agenda_digital[0]))
dict

agenda_digital = eval(agenda_digital[0])

agenda_digital # Nos devuelve por fin un diccionario
{'Alex Fernandez': {'Dirección': 'Calle Lorem Ipsum 57',
  'Email': 'lorem@ipsum.com',
  'Teléfono': '696 66 99 66'},
 'Fernando Moreno': {'Dirección': 'Calle Ipsum Lorem 89',
  'Email': 'ipsum@lorem.com',
  'Teléfono': '649 55 44 33'}}
```

{% hint style="info" %}
**Pista 4**: Recuerda que debes escribir una función, te recomiendo que tu función tenga una definición similar a la siguiente:
{% endhint %}

```python
def leer_agenda(nombre_agenda):
    <sentencias que leen la agenda digital de disco>
```

```python
def leer_agenda(nombre_agenda):
    """Lee la agenda digital de un fichero en disco
    Parámetros posicionales
    nombre_agenda -- str que representa el nombre de la agenda en disco
    """
    agenda_digital_lectura = open(nombre_agenda, "r")
    # Esta sentencia lee todas las líneas del fichero y las asigna a la variable agenda_digital
    agenda_digital = agenda_digital_lectura.readlines()
    # Esta sentencia cierra el fichero que has abierto con la función open()
    agenda_digital_lectura.close()
    return eval(agenda_digital[0])
```

## <mark style="color:blue;">4. Crea un menu para introducir un nombre en la agenda</mark>

Si has llegado hasta este apartado, ¡enhorabuena! ya has implementado gran parte de la funcionalidad de nuestra agenda digital. Ahora que tenemos funciones para escrbir y leer la agenda de un fichero que se encuentra almacenado en disco, necesitamos una función que nos permita crear nuevos contactos dentro de nuestra agenda.

Crea una función en Python que solicite los datos de un nuevo contacto de la agenda por pantalla al usuario y cree una nueva entrada en nuestra agenda digital

{% hint style="info" %}
**Pista:** Divide este apartado en dos funciones. En la primera función implementa el código que solicite al usuario por pantalla los campos necesarios para un nuevo contacto de la agenda. En la segunda función, implementa el código necesario para crear este nuevo contacto en la agenda digital. Te recomiendo que las funciones tengan una definición similar a la siguiente:
{% endhint %}

```python
def solicitar_contacto_agenda():
    <sentencias que solicitan los datos de un nuevo contacto>

def crear_contacto(agenda_digital, nuevo_contacto):
    <sentencias que crean el nuevo contacto en la agenda digital>
```

```python
def solicitar_contacto_agenda():
    """Esta función solicita los datos de un nuevo contacto al usuario"""
    nombre = input("Introduce el nombre completo del contacto: ")
    direccion = input("Introduce la dirección del contacto: ")
    email = input("Introduce el email del contacto: ")
    telefono = input("Introduce el teléfono del contacto: ")
    # Construímos un diccionario con los valores recibidos
    contacto = {
        "Nombre": nombre,
        "Dirección": direccion,
        "Email": email,
        "Teléfono": telefono,
    }
    return contacto
    
nuevo_contacto = solicitar_contacto_agenda()
Introduce el nombre completo del contacto: Javier Martinez
Introduce la dirección del contacto: Lorem ipsum 69
Introduce el email del contacto: lorem@ipsum.com
Introduce el teléfono del contacto: 687 65 67 66

nuevo_contacto
{'Nombre': 'Javier Martinez',
 'Dirección': 'Lorem ipsum 69',
 'Email': 'lorem@ipsum.com',
 'Teléfono': '687 65 67 66'}
```

```python
def crear_contacto(agenda_digital, nuevo_contacto):
    """Introduce un nuevo contacto en la agenda existente.
    Parámetro posicionales
    agenda_digital -- dict que representa la agenda digital existente
    nuevo_contacto -- dict que representa un nuevo contacto"""
    agenda_digital[nuevo_contacto["Nombre"]] = {
        "Dirección": nuevo_contacto["Dirección"],
        "Email": nuevo_contacto["Email"],
        "Teléfono": nuevo_contacto["Teléfono"]
    }
    return agenda_digital
    
crear_contacto(agenda_digital, nuevo_contacto)
{'Alex Fernandez': {'Dirección': 'Calle Lorem Ipsum 57',
  'Email': 'lorem@ipsum.com',
  'Teléfono': '696 66 99 66'},
 'Fernando Moreno': {'Dirección': 'Calle Ipsum Lorem 89',
  'Email': 'ipsum@lorem.com',
  'Teléfono': '649 55 44 33'},
 'Javier Martinez': {'Dirección': 'Lorem ipsum 69',
  'Email': 'lorem@ipsum.com',
  'Teléfono': '687 65 67 66'}}
```

## <mark style="color:blue;">5. Crea un menu para consultar un nombre de la agenda</mark>

¡Genial! Ya casi hemos terminado. Implementa una funcionalidad más en nuestra agenda que nos permita leer los datos relativos a un contacto existente.

Implementa una función en Python que solicte por pantalla el nombre completo de un contacto de la agenda y, a partir de ese nombre, nos proporcione el resto de información: dirección, email y teléfono...

```python
def consultar_contacto(agenda_digital):
    """Esta función consulta un contacto en la agenda"""
    nombre = input("Introduce el nombre completo del contacto: ")
    print("\n[+]", nombre)
    print("\tDirección:", agenda_digital[nombre]["Dirección"])
    print("\tEmail:", agenda_digital[nombre]["Email"])
    print("\tTeléfono:", agenda_digital[nombre]["Teléfono"])
    
consultar_contacto(agenda_digital)
Introduce el nombre completo del contacto: Javier Martinez

[+] Javier Martinez
	Dirección: Lorem ipsum 69
	Email: lorem@ipsum.com
	Teléfono: 687 65 67 66
```

## <mark style="color:blue;">6. Pon todo en común</mark>

Pon en común todas las funciones que has implementado en las secciones anteriores para mostrar la funcionalidad de tu agenda digital.

### **6.1. Crea un nuevo contacto en la agenda**

1. Lee la agenda digital de disco
2. Solicita los datos de un nuevo contacto por pantalla al usuario
3. Crea un nuevo contacto en la agenda digital
4. Escribe la agenda resultante en disco

```python
agenda_digital = leer_agenda("agenda_digital")
nuevo_contacto = solicitar_contacto_agenda()
agenda_digital = crear_contacto(agenda_digital, nuevo_contacto)
escribir_agenda(nombre_agenda, agenda_digital)
Introduce el nombre completo del contacto: Alex Fernandez
Introduce la dirección del contacto: lorem ipsum 66
Introduce el email del contacto: alex@fernandez.com
Introduce el teléfono del contacto: 666 77 88 99

agenda_digital
{'Alex Fernandez': {'Dirección': 'lorem ipsum 66',
  'Email': 'alex@fernandez.com',
  'Teléfono': '666 77 88 99'},
 'Fernando Moreno': {'Dirección': 'Calle Ipsum Lorem 89',
  'Email': 'ipsum@lorem.com',
  'Teléfono': '649 55 44 33'}}
```

### **6.2. Consulta un contacto existente de la agenda digital**

1. Lee la agenda digital de disco
2. Consulta un contacto existente

```python
agenda_digital = leer_agenda("agenda_digital")

consultar_contacto = consultar_contacto(agenda_digital)

Introduce el nombre completo del contacto: Alex Fernandez

[+] Alex Fernandez
	Dirección: Calle Lorem Ipsum 57
	Email: lorem@ipsum.com
	Teléfono: 696 66 99 66
```

## <mark style="color:blue;">7. Evolución del programa</mark>

Aquí podéis ver una evolución de este programa, añadiendo más funcionalidades

{% embed url="<https://github.com/afsh4ck/agenda>" %}

<figure><img src="/files/qzahqlpsmTncYzT6Ql3O" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://afsh4ck.gitbook.io/desarrollo-con-python/datos-complejos/caso-practico-agenda.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
