Skip to content
> 💻 🧠 Codice 1001 > 📚 Materiali di Apprendimento > 🐍 Python > Classi in Python, OOP e context manager: guida completa

Classi in Python, OOP e context manager: guida completa


1. Classi in Python

Le classi sono il cuore della OOP. Una classe è un modello per creare oggetti con attributi (dati) e metodi (funzioni). Gli oggetti creati da una classe sono chiamati istanze. Le classi aiutano a strutturare il codice, aumentano il riuso e semplificano la manutenzione.

Struttura di una classe

class ClassName:
    def __init__(self, param1, param2):
        self.param1 = param1
        self.param2 = param2

    def method(self):
        return f'{self.param1} e {self.param2}'

Punti chiave:

  • __init__: costruttore per inizializzare gli attributi dell’oggetto.
  • self: riferimento all’istanza corrente.
  • Attributi: definiti tramite self e accessibili in tutti i metodi.
  • Metodi: operano sui dati dell’oggetto.

Creazione di oggetti

class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year

    def description(self):
        return f'{self.year} {self.make} {self.model}'

my_car = Car('Toyota', 'Corolla', 2020)
print(my_car.description())  # Output: 2020 Toyota Corolla

Tipi di metodi

  1. Metodi di istanza — operano sull’oggetto (self).
  2. Metodi di classe — operano sulla classe (cls) usando @classmethod.
  3. Metodi statici — non dipendono né dall’istanza né dalla classe (@staticmethod).

Ereditarietà

class Animal:
    def speak(self):
        return 'Voce animale'

class Dog(Animal):
    def speak(self):
        return 'Bau'

Polimorfismo

class Cat(Animal):
    def speak(self):
        return 'Miao'

cat = Cat()
print(cat.speak())  # Output: Miao
  • Lo stesso metodo può avere comportamenti diversi a seconda del tipo di oggetto.

Incapsulamento

class Car:
    def __init__(self, make, model):
        self._make = make  # attributo protetto
        self._model = model

    def get_make(self):
        return self._make

    def set_make(self, make):
        self._make = make

Metodi speciali e distruttore

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

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

p = Point(3, 4)
print(p)  # Output: Point(3, 4)

Diagramma ASCII: ereditarietà e polimorfismo

       ┌─────────┐
       │ Animal  │
       └─────────┘
       │ speak() │
       └─────────┘
            ▲
    ┌───────┴────────┐
    │                │
┌─────────┐      ┌─────────┐
│  Dog    │      │  Cat    │
└─────────┘      └─────────┘
│ speak() │      │ speak() │
└─────────┘      └─────────┘

2. Context manager in Python

I context manager permettono di allocare e rilasciare automaticamente risorse, anche in caso di errori.

Uso di @contextmanager

from contextlib import contextmanager

@contextmanager
def my_context():
    print("Entrata nel contesto")
    try:
        yield "Risorsa"
    finally:
        print("Uscita dal contesto")

Esempio:

with my_context() as res:
    print("Nel contesto:", res)

Cattura stdout/stderr e pattern Tee

Python permette di catturare stdout, stderr o entrambi, e visualizzare e catturare contemporaneamente con il pattern Tee.


3. Esempio completo: oop_and_context.py

"""
oop_and_context.py

Esempi di classi, principi OOP e context manager in Python.
Include:
- Definizioni di classi, ereditarietà, polimorfismo, incapsulamento
- Metodi di istanza, classe e statici
- Metodi speciali e distruttore
- Context manager con @contextmanager
- Cattura stdout, stderr e entrambi
- Pattern Tee: visualizzazione e cattura
- Context manager basato su classe
"""

import sys
import io
from contextlib import contextmanager

# ==========================
# Parte 1: Classi e OOP
# ==========================

class Animal:
    """Classe base per animali."""
    def speak(self):
        return 'Voce animale'

class Dog(Animal):
    def speak(self):
        return 'Bau'

class Cat(Animal):
    def speak(self):
        return 'Miao'

class Car:
    """Esempio di incapsulamento."""
    def __init__(self, make, model, year=None):
        self._make = make
        self._model = model
        self.year = year

    def get_make(self):
        return self._make

    def set_make(self, make):
        self._make = make

    def description(self):
        if self.year:
            return f'{self.year} {self._make} {self._model}'
        return f'{self._make} {self._model}'

class Point:
    """Classe con metodi speciali."""
    def __init__(self, x, y):
        self.x = x
        self.y = y

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

# ==========================
# Parte 2: Context manager
# ==========================

@contextmanager
def my_context():
    print("Entrata nel contesto")
    try:
        yield "Risorsa"
    finally:
        print("Uscita dal contesto")

@contextmanager
def capture_stdout():
    old_stdout = sys.stdout
    sys.stdout = buffer = io.StringIO()
    try:
        yield buffer
    finally:
        sys.stdout = old_stdout

@contextmanager
def capture_stderr():
    old_stderr = sys.stderr
    sys.stderr = buffer = io.StringIO()
    try:
        yield buffer
    finally:
        sys.stderr = old_stderr

@contextmanager
def capture_output():
    old_stdout = sys.stdout
    old_stderr = sys.stderr
    sys.stdout = sys.stderr = buffer = io.StringIO()
    try:
        yield buffer
    finally:
        sys.stdout = old_stdout
        sys.stderr = old_stderr

class Tee(io.StringIO):
    """Visualizzazione e cattura contemporanea."""
    def __init__(self, original):
        super().__init__()
        self.original = original

    def write(self, text):
        self.original.write(text)
        super().write(text)

    def flush(self):
        self.original.flush()

@contextmanager
def capture_stdout_tee():
    old_stdout = sys.stdout
    sys.stdout = tee = Tee(old_stdout)
    try:
        yield tee
    finally:
        sys.stdout = old_stdout

# ==========================
# Parte 3: Context manager basato su classe
# ==========================

class OutputCapture:
    """Context manager per catturare stdout."""
    def __init__(self):
        self._buffer = io.StringIO()
        self._old_stdout = None

    def __enter__(self):
        self._old_stdout = sys.stdout
        sys.stdout = self._buffer
        return self._buffer

    def __exit__(self, exc_type, exc_val, exc_tb):
        sys.stdout = self._old_stdout
        return False  # propagare l'eccezione

# ==========================
# Parte 4: Dimostrazioni
# ==========================

def demo_classes():
    print("\n--- Dimostrazione classi ---")
    dog = Dog()
    cat = Cat()
    print("Il cane dice:", dog.speak())
    print("Il gatto dice:", cat.speak())

    my_car = Car('Toyota', 'Corolla', 2020)
    print("Descrizione auto:", my_car.description())
    my_car.set_make('Honda')
    print("Marca aggiornata:", my_car.get_make())

    point = Point(3, 4)
    print("Punto:", point)

def demo_context_managers():
    print("\n--- Dimostrazione context manager ---")

    with my_context() as res:
        print("Nel contesto:", res)

    with capture_stdout() as out:
        print("stdout catturato")
    print("Buffer:", out.getvalue().strip())

    with capture_stderr() as err:
        print("Va a stdout")
        sys.stderr.write("Messaggio di errore\n")
    print("Errore:", err.getvalue().strip())

    with capture_output() as out_all:
        print("stdout in cattura combinata")
        sys.stderr.write("stderr in cattura combinata\n")
    print("Output combinato:", out_all.getvalue().strip())

    with capture_stdout_tee() as tee_out:
        print("Output visibile e catturato (Tee)")
    print("Buffer Tee:", tee_out.getvalue().strip())

    with OutputCapture() as class_capture:
        print("Cattura tramite context manager di classe")
    print("Buffer context manager di classe:", class_capture.getvalue().strip())

# ==========================
# Esecuzione principale
# ==========================

if __name__ == "__main__":
    demo_classes()
    demo_context_managers()

Leave a Reply

Your email address will not be published. Required fields are marked *