Concepte de Classe en Python
Una classe és una plantilla que serveix per crear objectes. Defineix quins atributs (dades) i mètodes (funcions) tindran aquests objectes.
Exemple bàsic de definició de classe
class Cotxe:
def __init__(self, marca, model):
self.marca = marca
self.model = model
def mostrar_info(self):
print(f"{self.marca} {self.model}")
🚗 Creació d’objectes a partir de la classe
cotxe1 = Cotxe("Toyota", "Corolla")
cotxe2 = Cotxe("Ford", "Focus")
cotxe1.mostrar_info() # Toyota Corolla
cotxe2.mostrar_info() # Ford Focus
Parts d'una classe
| Component | Descripció |
|---|---|
class |
Paraula clau per crear una classe |
__init__() |
Constructor: defineix com s'inicialitza l’objecte |
self |
Referència a l'objecte actual |
| Atributs | Informació de l’objecte (com self.marca) |
| Mètodes | Funcions dins la classe (com mostrar_info()) |
🧾 Resum ràpid
| Concepte | Significat |
|---|---|
| Classe | Plantilla per crear objectes |
| Objecte | Instància concreta d’una classe |
| Atribut | Característica de l’objecte (com el nom o l’edat) |
| Mètode | Acció o comportament de l’objecte |
🎓 Exemple de la vida real
- Classe:
Persona - Objecte:
p1 = Persona("Anna", 30) - Atributs: nom, edat
- Mètodes: parlar(), caminar(), etc.
Estructura i Membres d'una Classe en Python
Una classe en Python és una plantilla per crear objectes. Conté atributs (dades) i mètodes (funcions) que defineixen el comportament i l’estat dels objectes.
Estructura bàsica
class NomClasse:
atribut_classe = valor
def __init__(self, paràmetres):
self.atribut_instancia = valor
def metode(self):
pass
Membres d'una classe
| Tipus | Descripció | Exemple |
|---|---|---|
| Atribut de classe | Compartit per tots els objectes | atribut_classe = 0 |
| Atribut d’instància | Únic per a cada objecte | self.nom = "Anna" |
| Constructor | Inicialitza l’objecte | def __init__(self): |
| Mètode d’instància | Opera sobre l’objecte (usa self) |
def parlar(self): |
| Mètode de classe | Opera sobre la classe (usa @classmethod) |
def crear(cls): |
| Mètode estàtic | No depèn ni de la classe ni de l’objecte | def ajuda(): |
Exemple complet
class Persona:
especie = "Humà" # Atribut de classe
def __init__(self, nom, edat):
self.nom = nom # Atribut d’instància
self.edat = edat
def saludar(self): # Mètode d’instància
print(f"Hola! Sóc {self.nom}.")
@classmethod
def info_especie(cls): # Mètode de classe
print(f"Tots som {cls.especie}")
@staticmethod
def ajuda(): # Mètode estàtic
print("Usa __init__ per crear objectes.")
Resum ràpid
| Membre | Funció | Accés |
|---|---|---|
atribut_classe |
Valor comú a tots els objectes | Classe.nom |
self.atribut |
Valor específic de cada objecte | Només via instància |
@classmethod |
Treballa amb la classe (cls) | Classe.metode() |
@staticmethod |
No usa ni self ni cls |
Classe.metode() |
__init__ |
Constructor de l'objecte | Executat automàticament |
Visibilitat en Classes en Python
En Python, la visibilitat determina si un atribut o mètode d'una classe és accessible des de fora. Python no fa servir paraules clau com public o private, però utilitza convencions amb els noms.
Tipus de visibilitat
| Tipus | Com s’escriu | Accessible des de fora? | Comentari |
|---|---|---|---|
| Pública | self.nom |
✅ Sí | Qualsevol pot accedir |
| Protegida | self._nom |
⚠️ Sí (es desaconsella) | Convenció per indicar ús intern |
| Privada | self.__nom |
🚫 No directament | Només accessible dins la classe |
🔧 Exemple de codi
class Persona:
def __init__(self, nom, edat):
self.nom = nom # Públic
self._edat = edat # Protegit
self.__dni = "12345678Z" # Privat
def mostrar_info(self):
print(f"Nom: {self.nom}, Edat: {self._edat}")
def mostrar_dni(self):
print(f"DNI: {self.__dni}")
p = Persona("Anna", 30)
print(p.nom) # ✅ Públic -> mostra : Anna
print(p._edat) # ⚠️ Protegit -> mostra: 30
# print(p.__dni) # ❌ Error: No accessible directament -> mostra error
p.mostrar_dni() # ✅ Accés a privat amb mètode -> mostra: DNI: 12345678Z
🔍 Name Mangling (accedir a atributs privats)
Els atributs privats es poden accedir si coneixes el nom intern generat per Python:
print(p._Persona__dni) # ✅ Possible (però no recomanat)
Resum ràpid
| Notació | Tipus | Accés extern | Ús recomanat |
|---|---|---|---|
atribut |
Públic | ✅ Sí | Per atributs oberts |
_atribut |
Protegit | ⚠️ Sí | Ús intern o per subclasses |
__atribut |
Privat | 🚫 No (excepte amb truc) | Per ocultar dades sensibles |
Mètodes especials
Mètodes màgics o “dunder”
Els mètodes especials comencen i acaben amb dos guions baixos (__). Se'ls anomena sovint “dunder” (de l'anglés “Double UNDERscore”).
__init__: Inicialitza un objecte. Sempre s’executa quan es crea una nova instància.__str__: Retorna una representació en forma de cadena de text de l’objecte (útil per imprimir-lo).__len__: Permet definir la longitud de l’objecte (quan s’utilitza amblen(obj)).
Exemple amb __str__
class Persona:
def __init__(self, nom, edat):
self.nom = nom
self.edat = edat
def __str__(self):
return f"{self.nom}, {self.edat} anys"
persona = Persona("Anna", 30)
print(persona) # Output: Anna, 30 anys
Altres mètodes dunder habituals:
__add__,__sub__: Per sumar o restar objectes.__eq__,__lt__,__gt__: Per comparar objectes (igual, menor, major).__iter__,__next__: Per fer iterables personalitzats (com en buclesfor).__getattr__,__setattr__,__delattr__: Per controlar l’accés i modificació d’atributs.
Per veure tots els mètodes i atributs disponibles d’un objecte pots utilitzar:
print(dir(obj))
Herència
La herència permet a una classe (filla) adquirir els atributs i mètodes d’una altra classe (pare). És un dels pilars de la POO i facilita la reutilització de codi i l’organització jeràrquica.
Estructura bàsica
class ClassePare:
# atributs i mètodes
class ClasseFilla(ClassePare):
# hereta tot i pot afegir o modificar
🧪 Exemple bàsic
class Animal:
def parlar(self):
print("Fa algun so")
class Gos(Animal):
def parlar(self): # sobrescriu
print("Bup bup!")
class Gat(Animal):
def parlar(self):
print("Miau!")
a = Animal()
a.parlar() # Fa algun so
g = Gos()
g.parlar() # Bup bup!
cat = Gat()
cat.parlar() # Miau!
Cridar el constructor del pare amb super()
class Persona:
def __init__(self, nom):
self.nom = nom
class Estudiant(Persona):
def __init__(self, nom, curs):
super().__init__(nom)
self.curs = curs
Notes:
super()s'utilitza per a cridar mètodes de la classe base.- Les subclasses poden sobrescriure mètodes de la classe base si necessiten comportament específic.
Encapsulació
En Python, pots controlar l'accés als atributs mitjançant modificadors d'accés:
- Públic (
nom): Es pot accedir des de qualsevol lloc. - Protegit (
_nom): Indica que és per a ús intern (per convenció). - Privat (
__nom): Només accessible dins de la classe.
Exemple:
class CompteBancari:
def __init__(self, titular, saldo):
self.titular = titular
self.__saldo = saldo # Atribut privat
def depositar(self, quantitat):
self.__saldo += quantitat
def mostrar_saldo(self):
print(f"Saldo: {self.__saldo}")
compte = CompteBancari("Carlos", 1000)
compte.depositar(500)
compte.mostrar_saldo() # Output: Saldo: 1500
Nota: Encara que els atributs privats no es poden accedir directament, es poden consultar mitjançant mètodes públics. Python també permet accedir-hi usant el nom modificat (_Classe__atribut), però això no es recomana.
Polimorfisme
El polimorfisme permet que diferents classes tinguen un mateix mètode però amb comportaments diferents.
Exemple:
class Au:
def so(self):
print("Cant genèric")
class Canari(Au):
def so(self):
print("Trinar")
class Ànec(Au):
def so(self):
print("Quac quac")
animals = [Canari(), Ànec(), Au()]
for animal in animals:
animal.so()
En aquest exemple, encara que totes les classes comparteixen el mètode so(), cada una executa una acció diferent. Això és una aplicació del polimorfisme.
Classes Iterables
Pots crear els teus propis iterables definint una classe que implemente els mètodes __iter__() i __next__(). Això et permet crear seqüències personalitzades que es poden recórrer amb bucles for.
Exemple d'un iterable personalitzat:
class Comptador:
def __init__(self, inici, fi):
self.inici = inici
self.fi = fi
def __iter__(self):
self.numero = self.inici
return self
def __next__(self):
if self.numero <= self.fi:
resultat = self.numero
self.numero += 1
return resultat
else:
raise StopIteration
comptador = Comptador(1, 5)
for numero in comptador:
print(numero)
En aquest exemple, la classe Comptador és un iterable que genera nombres del 1 al 5. El bucle for recorre cada nombre generat per l'iterable i el mostra per consola.