1. Introduzione agli operatori di appartenenza


# -----------------------------------------------
# -----------------------------------------------

# Verificare se un elemento è contenuto in una stringa
# Esempio: controllo se un carattere è presente in un testo

# Verificare se una parola è contenuta in una lista
# Esempio: lista della spesa, controllare presenza elemento

# Verificare se un valore NON è contenuto in una lista
# Esempio: controllo blacklist (not in)

# Membership su tuple
# Dimostrare che funziona anche su tuple (immutabili)

# Membership su dizionario (solo sulle chiavi!)
# Esempio: controllare se una chiave è presente in un inventario

# Membership su dizionario usando valori
# Usare: value in dict.values()

# -----------------------------------------------
# 2. Confronto di tipo con type()
# -----------------------------------------------

# Usare type() per verificare se una variabile è di tipo int
# Esempio: verificare input numerico

# Confronto errato da evitare:
# type(x) == float  (accettabile ma meno consigliato)

# mostrare che type() NON considera le sottoclassi
# Esempio: bool è sottoclasse di int → type() è rigido

# -----------------------------------------------
# 3. Confronto di tipo con isinstance()
# -----------------------------------------------

# Usare isinstance(x, int) come metodo preferibile

# isinstance con più tipi contemporaneamente
# Esempio: isinstance(x, (int, float)) per numeri in generale

# isinstance con oggetti personalizzati
# Esempio con classi (base + derivata)

# -----------------------------------------------
# 4. Combina membership e type checking
# -----------------------------------------------

# Verifica che un elemento sia nella lista E che sia di tipo int
# Esempio: lista con input misti, filtrare solo numeri validi

# Verifica che una variabile sia stringa e contenga un carattere specifico
# Esempio: controllo validità username

# -----------------------------------------------
# 5. Not in + type checking
# -----------------------------------------------

# Verificare che un elemento NON appartenga a una lista
# E che sia del tipo corretto prima di aggiungerlo
# Esempio: aggiunta sicura a una rubrica o inventario

# -----------------------------------------------
# 6. Membership in strutture complesse
# -----------------------------------------------

# Membership in liste di tuple (controllo su elementi complessi)

# Membership in liste di dizionari (mostrare perché 'in' è diverso)

# Verificare appartenenza di una chiave dentro una lista di dizionari
# Esempio: prodotto 'id' presente nei record

# -----------------------------------------------
# 7. Controlli utili nella pratica
# -----------------------------------------------

# Input utente: verificare che sia una stringa e NON vuota

# Validazione di password:
# - verificare che sia stringa
# - verificare presenza di caratteri speciali con 'in'

# Validazione elenco:
# Verificare che tutti gli elementi siano numeri (isinstance)
# Utilizzare all() per controllo globale

# -----------------------------------------------
# 8. Errori comuni da mostrare
# -----------------------------------------------

# Usare `x in y` su un numero → errore concettuale
# Esempio: 3 in 5 → non funziona

# Controllo tipo errato:
# type(x) == "str"  (sbagliato, confronta con la stringa)

# Confusione tra:
#   elemento in dizionario → controlla SOLO le chiavi
#   elemento in dizionario.values() → controlla valori