Els mètodes màgics en Python, també coneguts com a mètodes especials o dunder methods (per "double underscore"), són mètodes que tenen noms especials envoltats per dobles guions baixos, com __init__, __str__, __repr__, entre d'altres. Aquests mètodes permeten definir comportaments especials per a les instàncies de les classes, com la inicialització d'objectes, la representació en forma de cadena, la comparació, i molt més.

Conceptes Clau

  1. Mètodes d'Inicialització i Representació

    • __init__(self, ...): Inicialitza una nova instància de la classe.
    • __str__(self): Retorna una representació en forma de cadena llegible per a humans.
    • __repr__(self): Retorna una representació en forma de cadena que hauria de ser una expressió vàlida de Python que recrea l'objecte.
  2. Mètodes d'Operadors

    • __add__(self, other): Defineix el comportament de l'operador +.
    • __sub__(self, other): Defineix el comportament de l'operador -.
    • __mul__(self, other): Defineix el comportament de l'operador *.
    • __truediv__(self, other): Defineix el comportament de l'operador /.
  3. Mètodes de Comparació

    • __eq__(self, other): Defineix el comportament de l'operador ==.
    • __ne__(self, other): Defineix el comportament de l'operador !=.
    • __lt__(self, other): Defineix el comportament de l'operador <.
    • __le__(self, other): Defineix el comportament de l'operador <=.
    • __gt__(self, other): Defineix el comportament de l'operador >.
    • __ge__(self, other): Defineix el comportament de l'operador >=.
  4. Altres Mètodes Màgics

    • __len__(self): Retorna la longitud de l'objecte.
    • __getitem__(self, key): Permet accedir a elements utilitzant la notació de clau.
    • __setitem__(self, key, value): Permet assignar valors a elements utilitzant la notació de clau.
    • __delitem__(self, key): Permet eliminar elements utilitzant la notació de clau.

Exemples Pràctics

Exemple 1: __init__, __str__, i __repr__

class Persona:
    def __init__(self, nom, edat):
        self.nom = nom
        self.edat = edat

    def __str__(self):
        return f'{self.nom}, {self.edat} anys'

    def __repr__(self):
        return f'Persona(nom={self.nom!r}, edat={self.edat!r})'

# Creació d'una instància
persona = Persona('Joan', 30)

# Ús de __str__
print(persona)  # Sortida: Joan, 30 anys

# Ús de __repr__
print(repr(persona))  # Sortida: Persona(nom='Joan', edat=30)

Exemple 2: Mètodes d'Operadors

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, altre):
        return Vector(self.x + altre.x, self.y + altre.y)

    def __sub__(self, altre):
        return Vector(self.x - altre.x, self.y - altre.y)

    def __repr__(self):
        return f'Vector({self.x}, {self.y})'

# Creació de vectors
v1 = Vector(2, 3)
v2 = Vector(4, 5)

# Ús de __add__
v3 = v1 + v2
print(v3)  # Sortida: Vector(6, 8)

# Ús de __sub__
v4 = v1 - v2
print(v4)  # Sortida: Vector(-2, -2)

Exemple 3: Mètodes de Comparació

class Persona:
    def __init__(self, nom, edat):
        self.nom = nom
        self.edat = edat

    def __eq__(self, altre):
        return self.edat == altre.edat

    def __lt__(self, altre):
        return self.edat < altre.edat

    def __repr__(self):
        return f'Persona(nom={self.nom!r}, edat={self.edat!r})'

# Creació de persones
p1 = Persona('Joan', 30)
p2 = Persona('Maria', 25)
p3 = Persona('Anna', 30)

# Ús de __eq__
print(p1 == p3)  # Sortida: True

# Ús de __lt__
print(p2 < p1)  # Sortida: True

Exercicis Pràctics

Exercici 1: Implementar __len__ i __getitem__

Implementa una classe Llibre que tingui una llista de capítols. Defineix els mètodes __len__ per retornar el nombre de capítols i __getitem__ per accedir a un capítol específic per índex.

class Llibre:
    def __init__(self, titol, capitols):
        self.titol = titol
        self.capitols = capitols

    def __len__(self):
        return len(self.capitols)

    def __getitem__(self, index):
        return self.capitols[index]

    def __repr__(self):
        return f'Llibre(titol={self.titol!r}, capitols={self.capitols!r})'

# Creació d'un llibre
llibre = Llibre('Python per a Tothom', ['Introducció', 'Variables', 'Estructures de Control'])

# Ús de __len__
print(len(llibre))  # Sortida: 3

# Ús de __getitem__
print(llibre[1])  # Sortida: Variables

Exercici 2: Implementar __eq__ i __lt__ per a una Classe Producte

Implementa una classe Producte que tingui atributs nom i preu. Defineix els mètodes __eq__ per comparar productes pel seu preu i __lt__ per determinar si un producte és més barat que un altre.

class Producte:
    def __init__(self, nom, preu):
        self.nom = nom
        self.preu = preu

    def __eq__(self, altre):
        return self.preu == altre.preu

    def __lt__(self, altre):
        return self.preu < altre.preu

    def __repr__(self):
        return f'Producte(nom={self.nom!r}, preu={self.preu!r})'

# Creació de productes
p1 = Producte('Llibre', 20)
p2 = Producte('Llapis', 1)
p3 = Producte('Llibreta', 5)

# Ús de __eq__
print(p1 == p3)  # Sortida: False

# Ús de __lt__
print(p2 < p3)  # Sortida: True

Conclusió

Els mètodes màgics són una eina poderosa en Python que permeten personalitzar el comportament de les classes de manera molt flexible. Aquests mètodes permeten definir com les instàncies de les classes es comporten en diverses situacions, com la inicialització, la representació en forma de cadena, les operacions amb operadors, i molt més. La comprensió i l'ús adequat dels mètodes màgics poden fer que el teu codi sigui més intuïtiu i fàcil de mantenir.

Curs de Programació en Python

Mòdul 1: Introducció a Python

Mòdul 2: Estructures de Control

Mòdul 3: Funcions i Mòduls

Mòdul 4: Estructures de Dades

Mòdul 5: Programació Orientada a Objectes

Mòdul 6: Gestió de Fitxers

Mòdul 7: Gestió d'Errors i Excepcions

Mòdul 8: Temes Avançats

Mòdul 9: Proves i Depuració

Mòdul 10: Desenvolupament Web amb Python

Mòdul 11: Ciència de Dades amb Python

Mòdul 12: Projecte Final

© Copyright 2024. Tots els drets reservats