0Pricing
Python Academy · Lezione

TypeVar, classi generiche e Protocol

Definisca tipi generici riutilizzabili e il sottotipaggio strutturale con Protocol.

TypeVar, classi generiche e Protocol è una lezione Python Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Python Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Python Academy include 4 lezioni in totale.

Cos'è TypeVar?

TypeVar dichiara una variabile di tipo, ovvero un segnaposto che può rappresentare qualsiasi tipo, eventualmente con dei vincoli. Viene utilizzato nelle funzioni e nelle classi generiche.

from typing import TypeVar

T = TypeVar("T")

def identity(value: T) -> T:
    return value

print(identity(42))      # int
print(identity("hello")) # str

Funzioni generiche

Una funzione che utilizza TypeVar sia per i tipi dei parametri sia per il tipo restituito consente a mypy di dedurre il tipo restituito a partire dal tipo dell'argomento.

from typing import TypeVar

T = TypeVar("T")

def first(items: list[T]) -> T:
    return items[0]

x: int = first([1, 2, 3])     # mypy knows x is int
s: str = first(["a","b","c"]) # mypy knows s is str

TypeVar con vincoli

Passi dei vincoli di tipo a TypeVar per limitare i tipi accettabili.

from typing import TypeVar

Numeric = TypeVar("Numeric", int, float)

def double(n: Numeric) -> Numeric:
    return n * 2

print(double(5))    # 10
print(double(2.5))  # 5.0
# double("x")  # mypy error

Classi generiche

Erediti da Generic[T] per creare una classe parametrizzata da una variabile di tipo.

from typing import Generic, TypeVar

T = TypeVar("T")

class Stack(Generic[T]):
    def __init__(self) -> None:
        self._items: list[T] = []

    def push(self, item: T) -> None:
        self._items.append(item)

    def pop(self) -> T:
        return self._items.pop()

stack: Stack[int] = Stack()
stack.push(1)
print(stack.pop())   # 1

Più TypeVar

Utilizzi più TypeVar per parametrizzare una classe o una funzione con due tipi indipendenti.

from typing import Generic, TypeVar

K = TypeVar("K")
V = TypeVar("V")

class Pair(Generic[K, V]):
    def __init__(self, key: K, value: V) -> None:
        self.key = key
        self.value = value

p: Pair[str, int] = Pair("age", 30)
print(p.key, p.value)   # age 30

Protocol — Sottotipizzazione strutturale

Protocol definisce un'interfaccia in base ai metodi e agli attributi che una classe deve avere, senza richiedere un'ereditarietà esplicita ("duck typing, con controllo dei tipi").

from typing import Protocol

class Drawable(Protocol):
    def draw(self) -> None: ...

def render(obj: Drawable) -> None:
    obj.draw()

class Circle:
    def draw(self) -> None:
        print("Drawing circle")

render(Circle())   # works — Circle satisfies Drawable

Protocol con runtime_checkable

Aggiunga @runtime_checkable a un Protocol per abilitare i controlli isinstance() a runtime.

from typing import Protocol, runtime_checkable

@runtime_checkable
class Closeable(Protocol):
    def close(self) -> None: ...

class File:
    def close(self) -> None: print("closed")

print(isinstance(File(), Closeable))   # True

Protocol e ABC a confronto

Le ABC richiedono un'ereditarietà esplicita (class Dog(Animal)). I Protocol funzionano tramite corrispondenza strutturale: se una classe dispone dei metodi corretti, soddisfa il protocollo indipendentemente dall'ereditarietà.

from typing import Protocol
from abc import ABC, abstractmethod

# ABC: nominal typing
class Printable(ABC):
    @abstractmethod
    def display(self) -> None: ...

# Protocol: structural typing
class Displayable(Protocol):
    def display(self) -> None: ...

TypeVar con bound

TypeVar("T", bound=BaseClass) limita T a BaseClass o a una qualsiasi delle sue sottoclassi.

from typing import TypeVar

class Animal:
    def speak(self) -> str: return "..."

A = TypeVar("A", bound=Animal)

def make_speak(animal: A) -> str:
    return animal.speak()

Alias generici — Python 3.12

Python 3.12 introduce l'istruzione type per creare alias di tipo chiari e la sintassi class Foo[T] per i generici senza importare TypeVar.

# Python 3.12+
type Vector = list[float]
type Matrix = list[Vector]

class Stack[T]:
    def __init__(self) -> None: self._items: list[T] = []
    def push(self, item: T) -> None: self._items.append(item)
    def pop(self) -> T: return self._items.pop()

Tipo Self

Self (da typing in 3.11+) annota i metodi che restituiscono la classe corrente, risultando utile nelle interfacce fluent e nelle sottoclassi.

from typing import Self

class Builder:
    def __init__(self) -> None:
        self.parts: list[str] = []

    def add(self, part: str) -> Self:
        self.parts.append(part)
        return self

b = Builder().add("a").add("b")
print(b.parts)   # ["a", "b"]

Verifica rapida

Qual è la differenza fondamentale tra un Protocol e una ABC nel sistema di tipizzazione di Python?

Riepilogo

TypeVar crea segnaposto di tipo per funzioni e classi generiche. Generic[T] parametrizza le classi. Protocol abilita la sottotipizzazione strutturale senza ereditarietà. Utilizzi bound= o i vincoli di tipo su TypeVar per limitare i tipi accettabili.

Domande Frequenti

La lezione «TypeVar, classi generiche e Protocol» è gratuita?

Sì — il testo completo di «TypeVar, classi generiche e Protocol» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Python Academy, passa a CoddyKit PRO. Il corso Python Academy include 4 lezioni in totale.

Cosa imparerò in «TypeVar, classi generiche e Protocol»?

Definisca tipi generici riutilizzabili e il sottotipaggio strutturale con Protocol. Eserciti Python Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Python Academy?

Non è richiesta alcuna esperienza precedente. Python Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.

Quanto tempo richiede la lezione «TypeVar, classi generiche e Protocol»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Python Academy?

Sì. Ogni lezione Python Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Annotazioni di tipo di base
  2. Tipi complessi: List, Dict, Optional, Union
  3. TypeVar, classi generiche e Protocol
  4. Esecuzione di mypy e correzione degli errori di tipo
← Torna a Python Academy