Unes dades (o "data") és un un conjunt de valors que estan relacionats i que es gestionen com un conjunt.

Introducció

Hi ha variables que estan estretament relacionades entre elles.

Per exemple:

nom = "Eva"
cognom = "Vilaregut"
sexe = "Dona"

Els "objectes" ens permeten agrupar aquestes dades en un sóla variable i tractar-les de forma conjunta.

Diccionari

Els diccionars són objectes flexibles.

Són flexibles perquè pots afegir i modificar variables.

Un diccionari equival a un Object de Javascript: Objecte

A continuació crearem l'objecte eva:

eva = {"nom": "Eva", "cognom": "Vilaregut", "sexe": "Dona", "edat": 19}

D'aquesta manera tenim totes les dades agrupades.

Si vols accedir a l'edat de la Eva, pots utilitzar el nom de la variable (o "key") "edat":

assert eva["edat"] == 19

Però ves en compte, si la "key" no existeix ...

assert eva["altura"] == 162

Es produirà un error:

Traceback (most recent call last):
  File "/home/box/py/test.py", line 3, in <module>
    assert eva["altura"] == 162
           ~~~^^^^^^^^^^
KeyError: 'altura'

Si vull puc modificar l'edat de la Eva:

eva["edat"] = 18
assert eva["edat"] == 18

Si vull afegir l'altura de l'Eva:

eva["altura"] = 162
assert eva["altura"] == 162

Si vull borrar l'edat de l'eva:

del eva["edat"]
assert "edat" not in eva

Activitat: Llista d'objectes

A continuació tens una llista de persones:

persons = [
    {"nom": "Eva", "cognom": "Vilaregut", "sexe": "Dona", "edat": 19, "altura": 162},
    {"nom": "Joan", "cognom": "Sales", "sexe": "Home", "edat": 25, "altura": 173},
    {"nom": "Raquel", "cognom": "Viñales", "sexe": "Dona", "edat": 12, "altura": 123},
    {"nom": "Esther", "cognom": "Parra", "sexe": "Dona", "edat": 33, "altura": 178},
    {"nom": "Miquel", "cognom": "Amorós", "sexe": "Home", "edat": 56, "altura": 166},
    {"nom": "Laura", "cognom": "Casademunt", "sexe": "Dona", "edat": 41, "altura": 182},
]

1.- Quina és l'altura màxima?

result = max([p["altura"] for p in persons])
assert result == 182

2.- Quina és la mitja d'edat?

result = sum([p["edat"] for p in persons]) / len(persons)
assert result == 31

3.- Quina és la persona més alta?

result = persons[0]
for person in persons[1:]:
    if person["edat"] > result["edat"]:
        result = person

assert result["nom"] == "Laura"

4.- Imprimeix per pantall el nom i el cognom de totes les dones:

Eva Vilaregut
Raquel Viñales
Esther Parra
Laura Casademunt

[print(f"{person["nom"]} {person["cognom"]}") for person in persons if person["sexe"] == "Dona"]

Activitat: Treballar amb un objecte

Accés segur

eva = {"nom": "Eva", "cognom": "Vilaregut", "sexe": "Dona", "edat": 19, "altura": 162}

if "edat" in eva:
    assert eva["edat"] > 10

Totes les variables de l'objecte

eva = {"nom": "Eva", "cognom": "Vilaregut", "sexe": "Dona", "edat": 19, "altura": 162}

[print(f"{key}: {eva[key]}") for key in eva.keys()]

Dataclass

A vegades no necessitem objectes flexibles.

El que volem son objectes que només tingun un conjunt de variables predefinides (atributs).

D'aquesta manera podem estar segurs en el nostre codi que aquella variable (o atribut) de l'objecte existeix.

El que has de fer és definir una plantilla amb class anotada amb @dataclass:

from dataclasses import dataclass

@dataclass
class Country:
    name: str
    size: float = 0.0

Pots crear un pais molt més fàcilment que amb un dict:

spain = Country("Espanya", 504_030)

assert spain.name == "Espanya"

Però no pots crear un país amb la capital:

france = Country("France", "Paris", 675_417)
assert france.name == "France"

Si executes el codi:

Traceback (most recent call last):
  File "/home/box/py/test.py", line 12, in <module>
    france = Country("France", "Paris", 675_417)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: Country.__init__() takes from 2 to 3 positional arguments but 4 were given

Com tampoc pots accedir a l'atribut capital:

france = Country("France", 675_417)
assert france.capital == "Paris"

Es produeix un AttributeError:

Traceback (most recent call last):
  File "/home/box/py/test.py", line 13, in <module>
    assert france.capital == "Paris"
           ^^^^^^^^^^^^^^
AttributeError: 'Country' object has no attribute 'capital'

Continua llegint:

Activitats

A continuació tens una llista de paisos:

countries = [
    Country("France", 675_417),
    Country("Portugal", 92_152),
    Country("Espanya", 504_030)
]

1.- Digues quin és el país més gran?

result = countries[0]
for country in countries[1:]:
    if country.size > result.size:
        result = country

assert result.name == "France"

Tupla

Una tupla és una seqüència de mida fixa:

>>> t = ("a","b","c")
>>> t[0]
'a'
>>> t[0:2]
('a', 'b')
>>> t[3]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: tuple index out of range

És molt més eficient que un dict.

No necessites declarar una class de tipus @dataclass.

TODO

Activitat

A continuació tens una llista de paisos:

countries = [
    ("France", 675_417),
    ("Portugal", 92_152),
    ("Espanya", 504_030)
]

1.- Digues quin és el país més gran?

result = countries[0]
for country in countries[1:]:
    if country[1] > result[1]:
        result = country

assert result[0] == "France"