Conținut curs
Python Avansat
Despre lecție
  1. Introducere în decoratori de clasă și metode

    • Ce sunt decoratori de clasă și metode și de ce sunt utili
    • Exemple de decoratori în Python (property, staticmethod, classmethod, etc.)
    • Diferența dintre decoratori de funcții și decoratori de clasă și metode
  2. Crearea unui decorator de metodă simplu

    • Cum să creați un decorator de metodă
    • Exemplu: decorator pentru măsurarea timpului de execuție al unei metode
    • Exercițiu: creați un decorator de metodă pentru înregistrarea apelurilor
  3. Crearea unui decorator de metodă cu parametri

    • Cum să creați un decorator de metodă cu parametri
    • Exemplu: decorator pentru limitarea numărului de apeluri la o metodă
    • Exercițiu: creați un decorator de metodă pentru a adăuga un prefix la rezultatul unei metode
  4. Decoratori de metode de clasă și metode statice

    • Cum să folosiți decoratori pentru metode de clasă și metode statice
    • Exemplu: decorator pentru metode de clasă care adaugă o funcționalitate de logare
    • Exercițiu: creați un decorator de metodă statică pentru a adăuga o funcționalitate de memorare a rezultatelor
  5. Crearea unui decorator de clasă simplu

    • Cum să creați un decorator de clasă
    • Exemplu: decorator de clasă pentru adăugarea unei metode noi la o clasă
    • Exercițiu: creați un decorator de clasă pentru a adăuga o funcționalitate de verificare a tipului de date
  6. Crearea unui decorator de clasă cu parametri

    • Cum să creați un decorator de clasă cu parametri
    • Exemplu: decorator de clasă pentru a adăuga metode de comparare a obiectelor
    • Exercițiu: creați un decorator de clasă pentru a adăuga funcționalități de serializare și deserializare

Exemple și exerciții pentru fiecare subpunct:

Exemplu: decorator pentru măsurarea timpului de execuție al unei metode

python
import time

def cronometru_metoda(func):
    def wrapper(self, *args, **kwargs):
        start = time.time()
        result = func(self, *args, **kwargs)
        stop = time.time()
        print(f"Timpul de execuție al {func.__name__}: {stop - start:.2f} secunde")
        return result
    return wrapper

class Exemplu:
    @cronometru_metoda
    def metoda(self, n):
        time.sleep(n)

e = Exemplu()
e.metoda(2)  # Timpul de execuție al metoda: 2.00 secunde

Exercițiu:

Creați un decorator de metodă pentru înregistrarea apelurilor. Acest decorator ar trebui să înregistreze fiecare apel la o metodă și să permită accesarea log-urilor prin metoda afisare_loguri().

Exemplu: decorator pentru limitarea numărului de apeluri la o metodă

python
def limita_apeluri(limita):
    def decorator(func):
        def wrapper(self, *args, **kwargs):
            if wrapper.apeluri >= limita:
                raise Exception(f"Limita de {limita} apeluri pentru {func.__name__} a fost atinsă")
            result = func(self, *args, **kwargs)
            wrapper.apeluri += 1
            return result
        wrapper.apeluri = 0
        return wrapper
    return decorator

class Exemplu:
    @limita_apeluri(3)
    def metoda(self):
        print("Metoda apelată")

e = Exemplu()
e.metoda()  # Metoda apelată
e.metoda()  # Metoda apelată
e.metoda()  # Metoda apelată
e.metoda()  # Ridică Exception: Limita de 3 apeluri pentru metoda a fost atinsă

Exercițiu:

Creați undecorator de metodă pentru a adăuga un prefix la rezultatul unei metode. Decoratorul ar trebui să primească un parametru prefix și să îl adauge la începutul rezultatului metodei decorate.

Exemplu: decorator pentru metode de clasă care adaugă o funcționalitate de logare

python
def logare_clasametoda(func):
    def wrapper(cls, *args, **kwargs):
        print(f"Apelând metoda de clasă: {func.__name__}")
        return func(cls, *args, **kwargs)
    return wrapper

class Exemplu:
    @classmethod
    @logare_clasametoda
    def metoda_de_clasa(cls):
        print("Aceasta este o metoda de clasa")

Exemplu.metoda_de_clasa()
# Output:
# Apelând metoda de clasă: metoda_de_clasa
# Aceasta este o metoda de clasa

Exercițiu:

Creați un decorator de metodă statică pentru a adăuga o funcționalitate de memorare a rezultatelor. Acest decorator ar trebui să stocheze rezultatele metodei statice decorate și să le returneze direct fără a apela metoda din nou pentru aceleași argumente.

Exemplu: decorator de clasă pentru adăugarea unei metode noi la o clasă

python
def adauga_metoda_noua(metoda_noua):
    def decorator(cls):
        setattr(cls, metoda_noua.__name__, metoda_noua)
        return cls
    return decorator

def metoda_printare(self):
    print("Aceasta este o metoda noua")

@adauga_metoda_noua(metoda_printare)
class Exemplu:
    pass

e = Exemplu()
e.metoda_printare()  # Output: Aceasta este o metoda noua

Exercițiu:

Creați un decorator de clasă pentru a adăuga o funcționalitate de verificare a tipului de date. Acest decorator ar trebui să primească un parametru tip_de_date și să verifice dacă toate atributele obiectelor din clasa decorată au tipul specificat.

Exemplu: decorator de clasă pentru a adăuga metode de comparare a obiectelor

python
def adauga_comparare(tip_comparare):
    def decorator(cls):
        def __eq__(self, other):
            if tip_comparare == "adresa":
                return id(self) == id(other)
            elif tip_comparare == "valoare":
                return self.__dict__ == other.__dict__
            else:
                raise ValueError("Tip de comparare invalid")
        cls.__eq__ = __eq__
        return cls
    return decorator

@adauga_comparare("valoare")
class Exemplu:
    def __init__(self, x):
        self.x = x

e1 = Exemplu(1)
e2 = Exemplu(1)
e3 = Exemplu(2)

print(e1 == e2)  # Output: True (deoarece tip_comparare este "valoare")
print(e1 == e3)  # Output: False

Exercițiu:

Creați un decorator de clasă pentru a adăuga funcționalități de serializare și deserializare. Acest decorator ar trebui să adauge metodele serializare() și deserializare() la clasa decorată, care permit conversia obiectelor într-un format de date (de exemplu, JSON) și invers.