3. Variabili e tipi di dati di base
Nel Capitolo 2 hai imparato a scrivere semplici programmi che stampano testo, accettano input ed eseguono operazioni di base. Tuttavia, quei programmi avevano un limite significativo: non potevano memorizzare informazioni per un uso successivo né lavorare con diversi tipi di dati in modi sofisticati. In questo capitolo imparerai come Python memorizza e gestisce le informazioni usando variabili e tipi di dati.
Pensa alle variabili come a contenitori etichettati che contengono informazioni. Così come potresti usare scatole etichettate per organizzare gli oggetti in casa, Python usa le variabili per organizzare e gestire i dati nei tuoi programmi. Ma non tutti i dati sono uguali: un numero è fondamentalmente diverso dal testo, e Python deve sapere con che tipo di dato sta lavorando. È qui che entrano in gioco i tipi di dati.
Alla fine di questo capitolo capirai:
- Come creare e nominare correttamente le variabili
- Che cosa sono i tipi di dati e perché sono importanti
- Come lavorare con numeri, testo e valori logici
- Come convertire tra diversi tipi di dati
- Come Python rappresenta internamente i dati
Questi concetti costituiscono le fondamenta di tutto ciò che farai in Python, quindi li esploreremo a fondo e con molti esempi pratici.
3.1) Assegnare un nome e creare variabili
3.1.1) Che cosa sono le variabili e perché sono importanti
Una variabile è un nome che si riferisce a un valore memorizzato nella memoria del tuo computer. Quando crei una variabile, in pratica stai creando un’etichetta che punta a un certo dato. Questo ti permette di:
- Memorizzare informazioni per un uso successivo nel tuo programma
- Riferirti allo stesso valore più volte senza riscriverlo
- Aggiornare i valori mentre il programma è in esecuzione
- Rendere il codice leggibile usando nomi significativi invece di valori grezzi
Vediamo un esempio concreto. Senza variabili, se volessi calcolare l’area di un rettangolo, potresti scrivere:
# without_variables.py
print("Rectangle area:", 15 * 8)Questo funziona, ma cosa succede se devi usare queste dimensioni più volte? E che cosa rappresentano 15 e 8? Con le variabili, il codice diventa più chiaro e flessibile:
# with_variables.py
length = 15
width = 8
area = length * width
print("Rectangle area:", area) # Output: Rectangle area: 120Ora il codice è autoesplicativo: chiunque lo legga può capire immediatamente che stiamo calcolando l’area di un rettangolo con dimensioni specifiche. Se dobbiamo cambiare le dimensioni, basta aggiornare le assegnazioni delle variabili all’inizio.
3.1.2) Creare variabili con l’assegnazione
In Python crei una variabile usando l’operatore di assegnazione (=). La sintassi di base è:
variable_name = valueIl simbolo = non significa “uguale” nel senso matematico. Piuttosto significa “assegna il valore a destra al nome a sinistra”. Questa è una distinzione cruciale. Quando Python vede questa istruzione, esso:
- Valuta l’espressione sul lato destro di
= - Crea o aggiorna il nome di variabile sul lato sinistro
- Fa sì che quel nome si riferisca al valore risultante
Ecco diversi esempi di creazione di variabili:
# creating_variables.py
age = 25
temperature = 72.5
name = "Alice"
is_student = True
print(age) # Output: 25
print(temperature) # Output: 72.5
print(name) # Output: Alice
print(is_student) # Output: TrueNota che non dobbiamo dichiarare quale tipo di dato conterrà ogni variabile: Python lo deduce automaticamente in base al valore assegnato. Questo si chiama tipizzazione dinamica e rende Python molto flessibile e facile da usare.
Puoi anche creare più variabili in una sola riga usando l’assegnazione multipla:
# multiple_assignment.py
x, y, z = 10, 20, 30
print(x) # Output: 10
print(y) # Output: 20
print(z) # Output: 30
# You can even assign the same value to multiple variables
a = b = c = 100
print(a, b, c) # Output: 100 100 100La prima forma (chiamata tuple unpacking—impareremo cosa sono le tuple nel Capitolo 14) assegna ciascun valore alla variabile corrispondente nell’ordine. La seconda forma assegna lo stesso valore a tutte e tre le variabili.
3.1.3) Regole e convenzioni per i nomi delle variabili
Python ha regole specifiche su cosa costituisce un nome di variabile valido. Alcune sono obbligatorie (regole che devi seguire), altre sono convenzioni (linee guida che rendono il codice più leggibile e coerente con altro codice Python).
Requisiti (da seguire obbligatoriamente):
- Deve iniziare con una lettera (a-z, A-Z) o underscore (_): i nomi di variabile non possono iniziare con una cifra.
- Può contenere lettere, cifre e underscore: dopo il primo carattere puoi usare lettere, numeri e underscore in qualsiasi combinazione.
- Non può contenere spazi o caratteri speciali: spazi, trattini e la maggior parte dei segni di punteggiatura non sono ammessi.
- Non può essere una keyword di Python: Python riserva alcune parole per uso interno (come
if,for,while,def, ecc.). - Case-sensitive:
age,AgeeAGEsono tre variabili diverse.
Ecco esempi di nomi di variabile validi e non validi:
# valid_names.py
# Valid variable names
user_age = 30
firstName = "John"
total_2024 = 1000
_private = "hidden"
x = 5
MAX_SIZE = 100
# Invalid variable names (these will cause errors)
# 2nd_place = "silver" # Error: starts with digit
# user-name = "alice" # Error: contains hyphen
# total amount = 500 # Error: contains space
# class = "Python 101" # Error: 'class' is a keywordConvenzioni (da seguire per la leggibilità):
-
Usa minuscole con underscore per le variabili normali: questo stile si chiama
snake_caseed è lo standard in Python.pythonuser_age = 25 total_price = 99.99 is_valid = True -
Usa MAIUSCOLE per le costanti: valori che non dovrebbero cambiare durante l’esecuzione del programma.
pythonMAX_ATTEMPTS = 3 PI = 3.14159 DEFAULT_COLOR = "blue" -
Usa nomi descrittivi: i nomi delle variabili dovrebbero indicare chiaramente cosa rappresentano.
python# Good: clear and descriptive student_count = 30 average_temperature = 72.5 # Poor: unclear abbreviations sc = 30 avg_tmp = 72.5 # Poor: too generic x = 30 data = 72.5 -
Evita nomi a singola lettera tranne in casi specifici: singole lettere come
i,j,ksono accettabili come contatori di ciclo (che impareremo nel Capitolo 11), ex,y,zvanno bene per coordinate. In altri casi, usa nomi descrittivi. -
Non usare nomi che oscurano le funzioni built-in: anche se Python lo permette, evita nomi come
list,str,int,print, ecc., perché sono nomi di funzioni built-in.
Vediamo un esempio pratico che dimostra buone pratiche di denominazione:
# good_naming.py
# Constants at the top
SALES_TAX_RATE = 0.08
DISCOUNT_THRESHOLD = 100
# Descriptive variable names
item_price = 75.00
quantity = 3
subtotal = item_price * quantity
# Clear boolean variable
qualifies_for_discount = subtotal >= DISCOUNT_THRESHOLD
if qualifies_for_discount:
discount = subtotal * 0.10
subtotal = subtotal - discount
print("Discount applied: $", discount)
tax = subtotal * SALES_TAX_RATE
total = subtotal + tax
print("Subtotal: $", subtotal)
print("Tax: $", tax)
print("Total: $", total)
# Output:
# Subtotal: $ 202.5
# Tax: $ 16.2
# Total: $ 218.7Nota come i nomi delle variabili rendano il codice autoesplicativo. Anche senza commenti, puoi capire cosa sta calcolando il programma.
3.1.4) Usare le variabili nelle espressioni
Una volta che hai creato una variabile, puoi usarla ovunque useresti il valore che rappresenta. Python sostituisce automaticamente il valore corrente della variabile quando valuta le espressioni:
# using_variables.py
# Create some variables
hours_worked = 40
hourly_rate = 25.50
# Use variables in calculations
gross_pay = hours_worked * hourly_rate
print("Gross pay:", gross_pay) # Output: Gross pay: 1020.0
# Use variables in other expressions
bonus = gross_pay * 0.10
total_pay = gross_pay + bonus
print("Total with bonus:", total_pay) # Output: Total with bonus: 1122.0
# Use variables in strings (we'll learn more about this in Chapter 5)
message = "You worked " + str(hours_worked) + " hours"
print(message) # Output: You worked 40 hoursLe variabili possono anche essere usate con le funzioni che hai imparato nel Capitolo 2:
# variables_with_functions.py
name = input("What is your name? ")
age = input("What is your age? ")
greeting = "Hello, " + name + "!"
print(greeting)
age_next_year = int(age) + 1
print("Next year you will be", age_next_year, "years old.")
# If user enters "Alice" and "25":
# Output: Hello, Alice!
# Output: Next year you will be 26 years old.Questo esempio mostra anche un concetto importante: la funzione input() restituisce sempre testo (una stringa), quindi se vuoi farci operazioni matematiche devi prima convertirla in un numero. Esploreremo questo processo di conversione in dettaglio più avanti in questo capitolo (Sezione 3.7).
3.2) Assegnazione e riassegnazione delle variabili
3.2.1) Comprendere l’assegnazione
Quando assegni un valore a una variabile, Python crea una connessione tra il nome della variabile e il valore in memoria. È importante capire che la variabile non “contiene” il valore in senso fisico—piuttosto è un nome che si riferisce o punta a un valore memorizzato altrove in memoria.
Immaginala come un post-it con un nome scritto sopra, attaccato a una scatola che contiene il valore reale. La variabile (il post-it) non è il valore in sé—indica solo dove è memorizzato. Quando riassegni la variabile, sposti il post-it per puntare a un’altra scatola, non cambi ciò che c’era nella scatola originale.
Questa distinzione diventa importante quando parliamo di riassegnazione. Vediamo cosa succede quando assegni e riassegni variabili:
# assignment_basics.py
x = 10
print(x) # Output: 10
# Reassign x to a new value
x = 20
print(x) # Output: 20
# The old value (10) is gone; x now refers to 20Ecco cosa è successo passo dopo passo:
x = 10: Python crea il valore intero 10 in memoria e fa sì che il nomexvi si riferiscaprint(x): Python cerca a cosa si riferiscex(10) e lo stampax = 20: Python crea il valore intero 20 in memoria e fa sì chexsi riferisca a questo nuovo valoreprint(x): Python cerca a cosa si riferiscex(ora 20) e lo stampa
Il valore originale 10 esiste ancora in memoria temporaneamente, ma poiché nessuna variabile vi si riferisce più, il sistema di gestione automatica della memoria di Python (chiamato garbage collection) alla fine lo eliminerà.
3.2.2) Riassegnazione e aggiornamento delle variabili
Uno degli schemi più comuni nella programmazione è aggiornare una variabile in base al suo valore corrente. Ad esempio, potresti voler incrementare un contatore, aggiungere a un totale progressivo o modificare un valore in base a qualche calcolo:
# updating_variables.py
score = 0
print("Initial score:", score) # Output: Initial score: 0
# Add 10 points
score = score + 10
print("After first update:", score) # Output: After first update: 10
# Add 5 more points
score = score + 5
print("After second update:", score) # Output: After second update: 15
# Double the score
score = score * 2
print("After doubling:", score) # Output: After doubling: 30Analizziamo cosa succede in score = score + 10:
- Python valuta il lato destro:
score + 10 - Cerca il valore corrente di
score(0) - Calcola 0 + 10, ottenendo 10
- Assegna questo nuovo valore (10) a
score - Ora
scoresi riferisce a 10 invece che a 0
Questo schema è così comune che Python fornisce operatori abbreviati, che vedremo nel Capitolo 4 (Sezione 4.3). Per ora è importante capire la forma completa perché mostra chiaramente l’ordine delle operazioni: valuta completamente il lato destro, poi assegna al lato sinistro.
3.2.3) Le variabili sono indipendenti
Quando assegni una variabile a un’altra, Python copia il riferimento, non il valore stesso (per tipi semplici come numeri e stringhe). Tuttavia, per i tipi di base che stiamo imparando in questo capitolo, le variabili si comportano in modo indipendente dopo l’assegnazione:
# independent_variables.py
a = 10
b = a # b now refers to the same value as a (10)
print("a:", a) # Output: a: 10
print("b:", b) # Output: b: 10
# Change a
a = 20
print("After changing a:")
print("a:", a) # Output: a: 20
print("b:", b) # Output: b: 10 (unchanged!)Quando abbiamo assegnato b = a, abbiamo fatto sì che b si riferisse allo stesso valore a cui a si riferiva in quel momento (10). Quando in seguito abbiamo cambiato a facendolo riferire a 20, b non è stato toccato—si riferisce ancora a 10.
Questo comportamento è semplice per numeri e stringhe, ma diventa più complesso con collezioni come liste e dizionari. Lo esploreremo a fondo nel Capitolo 17 quando parleremo del modello a oggetti di Python e delle semantiche di riferimento.
3.2.4) Usare variabili prima dell’assegnazione
Un errore comune dei principianti è provare a usare una variabile prima che le sia stato assegnato un valore. Python genererà un NameError se ci provi:
# undefined_variable.py
print(total) # Error: NameError: name 'total' is not definedQuesto errore si verifica perché Python non sa a cosa si riferisca total: non l’hai ancora creata. La correzione è semplice: assegna prima un valore alla variabile:
# defined_variable.py
total = 0 # Initialize the variable first
print(total) # Output: 0
# Now we can update it
total = total + 10
print(total) # Output: 10Questo schema di inizializzare una variabile (assegnarle un valore iniziale) prima di usarla è fondamentale nella programmazione. Vedremo molti esempi di questo modello in tutto il libro, specialmente quando lavoreremo con contatori e accumulatori nei cicli (Capitolo 10).
3.2.5) Scambiare i valori delle variabili
Un’operazione comune è scambiare i valori di due variabili. In molti linguaggi di programmazione questo richiede una variabile temporanea:
# swap_with_temp.py
x = 10
y = 20
print("Before swap: x =", x, ", y =", y) # Output: Before swap: x = 10 , y = 20
# Swap using a temporary variable
temp = x # Save x's value
x = y # Put y's value in x
y = temp # Put saved value in y
print("After swap: x =", x, ", y =", y) # Output: After swap: x = 20 , y = 10Tuttavia Python fornisce un modo più elegante usando l’assegnazione simultanea:
# swap_pythonic.py
x = 10
y = 20
print("Before swap: x =", x, ", y =", y) # Output: Before swap: x = 10 , y = 20
# Swap in one line
x, y = y, x
print("After swap: x =", x, ", y =", y) # Output: After swap: x = 20 , y = 10Questo funziona perché Python valuta l’intero lato destro (y, x) prima di eseguire qualsiasi assegnazione. Crea quindi una struttura temporanea contenente i valori di y e x, poi “spacchetta” quei valori in x e y rispettivamente. È un bell’esempio della filosofia di Python di rendere semplici e leggibili le operazioni comuni.
3.3) Il concetto di tipi di dati e type()
3.3.1) Che cosa sono i tipi di dati?
Un tipo di dato (o semplicemente tipo) definisce che tipo di informazione un valore rappresenta e quali operazioni possono essere eseguite su di esso. Pensa ai tipi di dati come a categorie che dicono a Python come interpretare e trattare differenti tipi di informazione.
Per esempio:
- Il numero
42è un intero (numero intero) - Il numero
3.14è un numero a virgola mobile (numero con la virgola) - Il testo
"Hello"è una stringa (sequenza di caratteri) - Il valore
Trueè un booleano (valore logico vero/falso)
Perché i tipi di dati sono importanti? Perché tipi diversi supportano operazioni diverse:
# type_operations.py
# You can add numbers
result1 = 10 + 5
print(result1) # Output: 15
# You can also "add" strings (concatenation)
result2 = "Hello" + " " + "World"
print(result2) # Output: Hello World
# But you can't add a number and a string directly
# result3 = 10 + "5" # Error: TypeError: unsupported operand type(s)L’errore nell’ultimo esempio si verifica perché Python non sa come sommare un numero e una stringa: sono tipi di dati fondamentalmente diversi. Dovrebbe convertire il numero in testo e concatenarlo? Dovrebbe convertire il testo in numero e fare una somma matematica? Python richiede che tu sia esplicito su ciò che vuoi fare, convertendo un valore in modo che il tipo corrisponda a quello dell’altro (vedremo come nella Sezione 3.7).
3.3.2) Usare type() per controllare i tipi di dati
Python fornisce una funzione built-in chiamata type() che ti dice di che tipo è un valore o una variabile. Questo è estremamente utile per capire i tuoi dati e per il debugging:
# checking_types.py
# Check types of literal values
print(type(42)) # Output: <class 'int'>
print(type(3.14)) # Output: <class 'float'>
print(type("Hello")) # Output: <class 'str'>
print(type(True)) # Output: <class 'bool'>
# Check types of variables
age = 25
name = "Alice"
temperature = 98.6
is_valid = False
print(type(age)) # Output: <class 'int'>
print(type(name)) # Output: <class 'str'>
print(type(temperature)) # Output: <class 'float'>
print(type(is_valid)) # Output: <class 'bool'>L’output <class 'int'> significa “questo valore appartiene alla classe (tipo) chiamata int”. In Python, i tipi sono in realtà classi (impareremo le classi in dettaglio nella Parte VIII), ma per ora puoi considerare questi termini come intercambiabili.
3.3.3) Tipizzazione dinamica in Python
Python è un linguaggio a tipizzazione dinamica, il che significa che:
- Le variabili non hanno tipi fissi: una variabile può riferirsi a valori di tipi diversi in momenti diversi
- I tipi sono determinati a runtime: Python determina i tipi quando il programma viene eseguito, non quando scrivi il codice
- Non dichiari esplicitamente i tipi: a differenza di altri linguaggi, non devi dire “questa variabile conterrà un intero”
Ecco un esempio di tipizzazione dinamica in azione:
# dynamic_typing.py
x = 42
print(x, "is of type", type(x)) # Output: 42 is of type <class 'int'>
x = "Hello"
print(x, "is of type", type(x)) # Output: Hello is of type <class 'str'>
x = 3.14
print(x, "is of type", type(x)) # Output: 3.14 is of type <class 'float'>Nota come x possa riferirsi a valori di tipi diversi in punti diversi del programma. Python non si lamenta: aggiorna semplicemente il tipo a cui x si riferisce in quel momento.
Sebbene questa flessibilità sia comoda, significa anche che devi fare attenzione. Se ti aspetti che una variabile contenga un numero ma in realtà contiene una stringa, potresti ottenere errori imprevisti:
# type_confusion.py
value = "100" # This is a string, not a number!
# Trying to do math with it will fail
# result = value + 50 # Error: TypeError: can only concatenate str to str
# You need to convert it first
result = int(value) + 50
print(result) # Output: 150Per questo motivo capire i tipi di dati è cruciale: ti aiuta a prevedere quali operazioni funzioneranno e a intercettare gli errori prima che si manifestino.
3.3.4) Panoramica dei tipi built-in di Python
Python ha diversi tipi di dati built-in. In questo capitolo ci concentreremo sui più fondamentali:
In questo capitolo tratteremo:
- int: numeri interi (numeri interi)
- float: numeri a virgola mobile (numeri con la virgola)
- str: stringhe (testo)
- bool: valori booleani (True e False)
- NoneType: il valore speciale
None
Accenneremo brevemente ai numeri complex (numeri con una componente immaginaria), ma sono raramente necessari nella programmazione quotidiana. I tipi collezione (come list, tuple, dict e set) sono così importanti che abbiamo dedicato loro interi capitoli nella Parte IV.
3.3.5) Controllare i tipi nella pratica
Capire i tipi diventa particolarmente importante quando lavori con input dell’utente o dati provenienti da sorgenti esterne. Ricorda che input() restituisce sempre una stringa, anche se l’utente digita un numero:
# input_types.py
user_input = input("Enter a number: ")
print("You entered:", user_input)
print("Type:", type(user_input)) # Output: Type: <class 'str'>
# Even if user types "42", it's still a string!
# To use it as a number, convert it:
number = int(user_input)
print("As a number:", number)
print("Type:", type(number)) # Output: Type: <class 'int'>
# Now we can do math with it
doubled = number * 2
print("Doubled:", doubled)Quando esegui questo programma e inserisci 42, vedrai:
Enter a number: 42
You entered: 42
Type: <class 'str'>
As a number: 42
Type: <class 'int'>
Doubled: 84Questo dimostra un punto cruciale: la stringa "42" e l’intero 42 sono cose diverse in Python, anche se sembrano simili quando vengono stampati. La stringa è una sequenza di due caratteri ('4' e '2'), mentre l’intero è un valore numerico che può essere usato in operazioni matematiche.
3.4) Numeri interi e numeri a virgola mobile
3.4.1) Interi (int)
Un intero (tipo int) è un numero intero senza parte decimale. Gli interi possono essere positivi, negativi o zero e, in Python 3, possono essere arbitrariamente grandi—limitati solo dalla memoria disponibile del tuo computer.
# integers.py
# Positive integers
age = 25
year = 2024
population = 8000000000
# Negative integers
temperature = -15
debt = -5000
# Zero
balance = 0
# Very large integers (Python handles these easily)
huge_number = 123456789012345678901234567890
print(huge_number) # Output: 123456789012345678901234567890
print(type(huge_number)) # Output: <class 'int'>Python ti consente di scrivere numeri grandi con underscore per migliorarne la leggibilità. Gli underscore sono ignorati da Python ma rendono i numeri più facili da leggere per gli esseri umani:
# readable_numbers.py
# These are all the same number
million = 1000000
million = 1_000_000 # Much easier to read!
# Works with any size
population = 8_000_000_000
national_debt = 31_000_000_000_000
print(million) # Output: 1000000 (underscores not shown in output)
print(population) # Output: 8000000000Puoi anche scrivere interi in basi numeriche diverse usando prefissi speciali:
# number_bases.py
# Binary (base 2) - prefix 0b
binary = 0b1010 # This is 10 in decimal
print(binary) # Output: 10
# Octal (base 8) - prefix 0o
octal = 0o12 # This is 10 in decimal
print(octal) # Output: 10
# Hexadecimal (base 16) - prefix 0x
hexadecimal = 0xFF # This is 255 in decimal
print(hexadecimal) # Output: 255Queste basi alternative sono utili in alcuni contesti (come lavorare con i colori nel web design o nella programmazione di basso livello), ma nella maggior parte della programmazione quotidiana userai interi decimali normali.
3.4.2) Numeri a virgola mobile (float)
Un numero a virgola mobile (tipo float) è un numero con la virgola decimale. I float sono usati per rappresentare numeri reali—valori che non sono necessariamente interi:
# floats.py
# Numbers with decimal points
price = 19.99
temperature = 98.6
pi = 3.14159
# Very small numbers
electron_mass = 0.00000000000000000000000000000091093837
# Very large numbers
speed_of_light = 299792458.0
print(price) # Output: 19.99
print(temperature) # Output: 98.6
print(electron_mass) # Output: 9.1093837e-31 (scientific notation)
print(speed_of_light) # Output: 299792458.0Nota che float molto piccoli o molto grandi vengono mostrati in notazione scientifica (o notazione esponenziale). La notazione 9.1093837e-31 significa “9.1093837 × 10⁻³¹” ovvero “9.1093837 diviso per 10 elevato alla 31ª potenza”.
Puoi anche scrivere direttamente i float in notazione scientifica:
# scientific_notation.py
# These are equivalent
avogadro = 602214076000000000000000.0
avogadro = 6.02214076e23 # Much more readable!
# Small numbers
planck = 0.000000000000000000000000000000000662607015
planck = 6.62607015e-34 # Much more readable!
print(avogadro) # Output: 6.02214076e+23
print(planck) # Output: 6.62607015e-34La e (o E) sta per “esponente”. Il numero dopo e ti dice di quante posizioni spostare la virgola (positivo significa a destra, negativo a sinistra).
3.4.3) Interi vs float: differenze importanti
Sebbene interi e float rappresentino entrambi numeri, ci sono differenze importanti:
1. Precisione e rappresentazione:
Gli interi sono esatti—il valore 42 è esattamente 42, senza approssimazioni. I float, invece, sono approssimazioni a causa di come i computer memorizzano i numeri decimali in binario:
# float_precision.py
# This might surprise you!
result = 0.1 + 0.2
print(result) # Output: 0.30000000000000004
# The result isn't exactly 0.3 due to floating-point representation
print(result == 0.3) # Output: FalseQuesto non è un bug, ma una limitazione fondamentale di come i computer rappresentano i numeri decimali. Ne parleremo in dettaglio nel Capitolo 4 (Sezione 4.10), ma per ora ti basta sapere che i calcoli con i float potrebbero non essere perfettamente precisi.
2. Operazioni e risultati:
Quando esegui operazioni con interi e float, Python segue regole specifiche:
# int_float_operations.py
# Integer operations
int_result = 10 + 5
print(int_result, type(int_result)) # Output: 15 <class 'int'>
# Float operations
float_result = 10.0 + 5.0
print(float_result, type(float_result)) # Output: 15.0 <class 'float'>
# Mixed operations: result is always float
mixed_result = 10 + 5.0
print(mixed_result, type(mixed_result)) # Output: 15.0 <class 'float'>
# Division always returns float, even with integers
division_result = 10 / 5
print(division_result, type(division_result)) # Output: 2.0 <class 'float'>La regola chiave: qualsiasi operazione che coinvolga almeno un float produce un risultato float. Ha senso, perché i float possono rappresentare un intervallo più ampio di valori (inclusi i non interi), quindi Python “promuove” il risultato al tipo più generale.
3. Memoria e prestazioni:
Gli interi usano meno memoria e sono più veloci da elaborare rispetto ai float. Per la maggior parte dei programmi questa differenza è trascurabile, ma può essere importante in applicazioni critiche per le prestazioni o quando si lavora con dataset molto grandi.
3.4.4) Quando usare int e quando usare float
Ecco alcune linee guida pratiche per scegliere tra interi e float:
Usa gli interi quando:
- Conti elementi discreti (persone, oggetti, iterazioni)
- Rappresenti quantità esatte che non possono essere frazionarie (numero di studenti, numero di clic)
- Lavori con indici o posizioni in una sequenza
- Serve aritmetica esatta
# use_integers.py
student_count = 30 # Can't have 30.5 students
page_number = 42 # Can't be on page 42.7
loop_counter = 0 # Counting iterationsUsa i float quando:
- Rappresenti misure (temperatura, distanza, peso)
- Lavori con denaro (anche se bisogna fare attenzione alla precisione—ne parleremo nel Capitolo 4)
- Calcoli rapporti, percentuali o medie
- Sono accettabili valori approssimati
# use_floats.py
temperature = 72.5 # Temperature can be fractional
price = 19.99 # Money amounts have cents
average_score = 87.3 # Averages are often fractional
percentage = 0.15 # 15% as a decimal3.5) Letterali stringa e booleani (una rapida anteprima)
In questa sezione introdurremo brevemente altri due tipi di dati fondamentali: stringhe e booleani. Tratteremo le stringhe in modo molto più approfondito nei Capitoli 5 e 6, e i booleani in dettaglio nel Capitolo 7, ma hai bisogno di una comprensione di base già ora per scrivere anche solo semplici programmi.
3.5.1) Basi delle stringhe
Una stringa (tipo str) è una sequenza di caratteri—sostanzialmente, del testo. Crei stringhe racchiudendo il testo tra virgolette. Python accetta sia virgolette singole (') sia doppi apici ("):
# string_basics.py
# Single quotes
name = 'Alice'
message = 'Hello, World!'
# Double quotes (exactly equivalent)
name = "Alice"
message = "Hello, World!"
# Print them
print(name) # Output: Alice
print(message) # Output: Hello, World!
print(type(name)) # Output: <class 'str'>Sia le virgolette singole sia i doppi apici funzionano in modo identico: scegli quelli che preferisci, ma sii coerente nel tuo codice. Molti programmatori Python preferiscono i doppi apici perché sono più comuni in altri linguaggi, ma le virgolette singole sono altrettanto valide.
Perché averli entrambi? Il motivo principale è la comodità quando la tua stringa contiene delle virgolette:
# quotes_in_strings.py
# Use double quotes when string contains single quotes
sentence = "It's a beautiful day!"
print(sentence) # Output: It's a beautiful day!
# Use single quotes when string contains double quotes
speech = 'She said, "Hello!"'
print(speech) # Output: She said, "Hello!"
# Or use escape sequences (we'll learn more in Chapter 5)
sentence = 'It\'s a beautiful day!' # \' means a literal single quote
speech = "She said, \"Hello!\"" # \" means a literal double quoteLe stringhe possono essere vuote (non contenere alcun carattere):
# empty_string.py
empty = ""
also_empty = ''
print(empty) # Output: (nothing—it's empty!)
print(len(empty)) # Output: 0 (we'll learn about len() later)
print(type(empty)) # Output: <class 'str'>Puoi combinare stringhe usando l’operatore + (chiamato concatenazione):
# string_concatenation.py
first_name = "John"
last_name = "Doe"
full_name = first_name + " " + last_name
print(full_name) # Output: John Doe
# Be careful: you can't concatenate strings and numbers directly
age = 25
# message = "I am " + age + " years old" # Error: TypeError
# Convert the number to a string first
message = "I am " + str(age) + " years old"
print(message) # Output: I am 25 years oldEsploreremo le stringhe molto più a fondo nei Capitoli 5 e 6, includendo le sequenze di escape, i metodi delle stringhe, la formattazione e l’elaborazione del testo. Per ora, ricorda solo che le stringhe rappresentano testo e si creano con le virgolette.
3.5.2) Basi dei booleani
Un booleano (tipo bool) è un valore logico che può essere True o False. Questi sono i soli due valori booleani in Python e vengono usati per rappresentare verità e falsità nelle operazioni logiche:
# boolean_basics.py
# Boolean literals
is_sunny = True
is_raining = False
print(is_sunny) # Output: True
print(is_raining) # Output: False
print(type(is_sunny)) # Output: <class 'bool'>Importante: I valori booleani True e False devono essere scritti esattamente con questa capitalizzazione. Python distingue tra maiuscole e minuscole, quindi true, TRUE, false e FALSE non funzionano:
# boolean_case.py
correct = True # Correct
# wrong = true # Error: NameError: name 'true' is not defined
# wrong = TRUE # Error: NameError: name 'TRUE' is not definedI booleani provengono tipicamente da confronti o operazioni logiche:
# boolean_from_comparisons.py
age = 25
# Comparison operators produce boolean results
is_adult = age >= 18
print(is_adult) # Output: True
is_senior = age >= 65
print(is_senior) # Output: False
# You can use booleans in conditions (we'll learn more in Chapter 8)
if is_adult:
print("You can vote!") # Output: You can vote!
if is_senior:
print("You get a senior discount!") # (no output—condition is False)Operatori di confronto comuni che producono booleani:
==: uguale a!=: diverso da<: minore di>: maggiore di<=: minore o uguale a>=: maggiore o uguale a
# comparison_operators.py
x = 10
y = 20
print(x == y) # Output: False (10 is not equal to 20)
print(x != y) # Output: True (10 is not equal to 20)
print(x < y) # Output: True (10 is less than 20)
print(x > y) # Output: False (10 is not greater than 20)
print(x <= 10) # Output: True (10 is less than or equal to 10)
print(y >= 20) # Output: True (20 is greater than or equal to 20)Nota importante: Non confondere = (assegnazione) con == (confronto):
x = 10significa “assegna il valore 10 a x”x == 10significa “controlla se x è uguale a 10” (restituisce True o False)
# assignment_vs_comparison.py
x = 10 # Assignment: x now refers to 10
result = (x == 10) # Comparison: is x equal to 10?
print(result) # Output: True
# This is a common mistake for beginners:
# if x = 10: # Error: SyntaxError: can't use assignment in if condition
if x == 10: # Correct: comparison
print("x is 10") # Output: x is 10Esploreremo i booleani in modo molto più dettagliato nel Capitolo 7, includendo gli operatori logici (and, or, not), il concetto di veridicità (truthiness) e falsità (falsiness) e come Python usa i booleani nelle condizioni. Per ora, ricorda solo che i booleani rappresentano valori True/False e derivano tipicamente da confronti.
3.5.3) Stringhe e booleani nel contesto
Vediamo come stringhe e booleani lavorano insieme in un semplice esempio pratico:
# strings_booleans_example.py
# Get user input
name = input("What is your name? ")
age_input = input("What is your age? ")
# Convert age to integer
age = int(age_input)
# Create boolean conditions
is_adult = age >= 18
is_child = age < 13
# Build messages using strings
if is_adult:
status = "adult"
else:
status = "minor"
# Combine everything in output
print("Hello, " + name + "!")
print("You are an " + status + ".")
if is_child:
print("You are a child.")
# When user enters "Alice" and "16":
# Output: Hello, Alice!
# Output: You are a minor.Questo esempio mostra come i diversi tipi di dati lavorano insieme: stringhe per il testo, interi per i numeri e booleani per le decisioni logiche. Questa interazione tra tipi è fondamentale per tutta la programmazione.
3.6) Il valore None e i suoi utilizzi
3.6.1) Che cos’è None?
Python ha un valore speciale chiamato None (tipo NoneType) che rappresenta l’assenza di un valore. È il modo di Python di dire “qui non c’è nulla” o “questo non ha ancora un valore”.
# none_basics.py
result = None
print(result) # Output: None
print(type(result)) # Output: <class 'NoneType'>None non è la stessa cosa di zero, di una stringa vuota o di False: è un valore distinto che significa specificamente “nessun valore”:
# none_vs_others.py
x = None
y = 0
z = ""
w = False
print(x) # Output: None
print(y) # Output: 0
print(z) # Output: (empty—nothing prints)
print(w) # Output: False
# They're all different types
print(type(x)) # Output: <class 'NoneType'>
print(type(y)) # Output: <class 'int'>
print(type(z)) # Output: <class 'str'>
print(type(w)) # Output: <class 'bool'>3.6.2) Quando si usa None
None compare in diverse situazioni comuni:
1. Come segnaposto per valori che assegnerai in seguito:
# none_placeholder.py
# Initialize variables that will be assigned later
user_name = None
user_age = None
# Later in the program, after getting user input:
user_name = input("Enter your name: ")
user_age = int(input("Enter your age: "))
print("Name:", user_name)
print("Age:", user_age)2. Come valore di ritorno predefinito di funzioni che non restituiscono esplicitamente nulla:
Le funzioni che impareremo nel Capitolo 19 possono restituire valori. Se una funzione non restituisce esplicitamente nulla, Python restituisce automaticamente None:
# none_from_function.py
# The print() function returns None
result = print("Hello!") # Output: Hello!
print(result) # Output: None
print(type(result)) # Output: <class 'NoneType'>Può sembrare strano, ma è utile. Significa che ogni funzione restituisce qualcosa, anche se quel qualcosa è “nessun valore significativo”.
3. Per rappresentare dati opzionali o mancanti:
# none_optional.py
# Representing optional middle name
first_name = "John"
middle_name = None # No middle name
last_name = "Doe"
if middle_name is None:
full_name = first_name + " " + last_name
else:
full_name = first_name + " " + middle_name + " " + last_name
print(full_name) # Output: John Doe3.6.3) Controllare se un valore è None
Per controllare se un valore è None, usa l’operatore is (non ==):
# checking_none.py
value = None
# Correct way: use 'is'
if value is None:
print("Value is None") # Output: Value is None
# Also correct: use 'is not'
if value is not None:
print("Value has a value")
else:
print("Value is None") # Output: Value is None
# While == works, 'is' is preferred for None
if value == None: # This works but is not idiomatic Python
print("Value is None") # Output: Value is NonePerché usare is invece di ==? L’operatore is controlla se due nomi si riferiscono esattamente allo stesso oggetto in memoria (vedremo di più su questo nel Capitolo 17). Poiché in Python esiste un solo oggetto None, is è allo stesso tempo più efficiente e più preciso per questo controllo. Usare is None è l’idioma standard in Python.
3.6.4) None nell’uso pratico
Ecco un esempio pratico che mostra quanto None sia utile nei programmi reali:
# none_practical.py
# Simulate looking up a user's age
# (In real programs, we'd use functions and dictionaries from later chapters)
user_name = input("Enter a name (Alice, Bob, or Charlie): ")
# Check each name and assign age or None
if user_name == "Alice":
user_age = 25
elif user_name == "Bob":
user_age = 30
elif user_name == "Charlie":
user_age = 35
else:
user_age = None # User not found
# Check if we found the user
if user_age is not None:
print(user_name, "is", user_age, "years old")
else:
print(user_name, "not found")
# When user enters "Alice":
# Output: Alice is 25 years old
# When user enters "David":
# Output: David not foundIn questo esempio, None indica chiaramente “utente non trovato”, che è diverso dal trovare un utente con età 0 (che sarebbe un’età valida per un neonato).
3.6.5) None vs valori vuoti
È importante distinguere None dai valori vuoti:
# none_vs_empty.py
# These are all different
nothing = None
zero = 0
empty_string = ""
# Note: We'll learn about lists in Chapter 13
# empty_list = []
print(nothing is None) # Output: True
print(zero is None) # Output: False
print(empty_string is None) # Output: False
# None means "no value"
# 0 means "the number zero"
# "" means "text with no characters"Ognuno di questi rappresenta un concetto diverso:
None: assenza di un valore0: uno specifico valore numerico (zero)"": una stringa esistente ma senza caratteri
Capire questa distinzione ti aiuterà a scrivere programmi più chiari e corretti.
3.7) Conversione di tipo di base con int(), float() e str()
3.7.1) Perché la conversione di tipo è necessaria
Come abbiamo visto, Python ha regole rigide su quali operazioni funzionano con quali tipi. Non puoi sommare un numero e una stringa, moltiplicare una stringa per un float o eseguire operazioni matematiche sul testo. Quando hai bisogno di usare un valore come se fosse di un altro tipo, devi convertirlo esplicitamente.
La conversione di tipo (chiamata anche type casting) è il processo di trasformare un valore da un tipo a un altro. Python fornisce funzioni built-in per le conversioni più comuni:
int(): converte in interofloat(): converte in numero a virgola mobilestr(): converte in stringa
Esploriamo ciascuna di queste in dettaglio.
3.7.2) Convertire in intero con int()
La funzione int() converte un valore in un intero. Ecco i casi d’uso principali:
Convertire float in interi:
# float_to_int.py
# int() truncates (cuts off) the decimal part
x = int(3.14)
y = int(3.99)
z = int(-2.7)
print(x) # Output: 3 (not 4—it doesn't round!)
print(y) # Output: 3 (not 4—it truncates!)
print(z) # Output: -2 (truncates toward zero)Importante: int() non arrotonda—si limita a rimuovere la parte decimale (tronca verso zero). È una fonte comune di confusione per i principianti che si aspettano che int(3.9) restituisca 4.
Convertire stringhe in interi:
Questo è estremamente comune quando si lavora con input dell’utente:
# string_to_int.py
# Convert string containing a number
age_str = "25"
age_int = int(age_str)
print(age_str, type(age_str)) # Output: 25 <class 'str'>
print(age_int, type(age_int)) # Output: 25 <class 'int'>
# Now we can do math with it
next_year = age_int + 1
print("Next year:", next_year) # Output: Next year: 26
# Practical example with input()
user_age = int(input("Enter your age: "))
print("In 10 years, you'll be", user_age + 10)Cosa succede con conversioni non valide?
Se provi a convertire una stringa che non rappresenta un intero valido, Python genera un ValueError:
# invalid_int_conversion.py
# These work
print(int("123")) # Output: 123
print(int("-456")) # Output: -456
print(int(" 789 ")) # Output: 789 (whitespace is ignored)
# These don't work
# print(int("12.5")) # Error: ValueError: invalid literal for int()
# print(int("hello")) # Error: ValueError: invalid literal for int()
# print(int("12 34")) # Error: ValueError: invalid literal for int()Impareremo come gestire questi errori in modo sicuro nel Capitolo 27, quando parleremo di gestione delle eccezioni. Per ora ti basta sapere che devi assicurarti che le stringhe contengano rappresentazioni intere valide prima di convertirle.
Convertire booleani in interi:
I booleani possono essere convertiti in interi, dove True diventa 1 e False diventa 0:
# bool_to_int.py
print(int(True)) # Output: 1
print(int(False)) # Output: 0
# This is sometimes useful in calculations
is_premium = True
is_student = False
# Calculate discount (10% for premium, 5% for students)
discount = int(is_premium) * 0.10 + int(is_student) * 0.05
print("Discount:", discount) # Output: Discount: 0.1Tuttavia, usare booleani direttamente nell’aritmetica è generalmente sconsigliato perché rende il codice meno leggibile. Ne parleremo di più nel Capitolo 7.
3.7.3) Convertire in float con float()
La funzione float() converte un valore in numero a virgola mobile:
Convertire interi in float:
# int_to_float.py
x = float(42)
y = float(-17)
z = float(0)
print(x, type(x)) # Output: 42.0 <class 'float'>
print(y, type(y)) # Output: -17.0 <class 'float'>
print(z, type(z)) # Output: 0.0 <class 'float'>Convertire stringhe in float:
# string_to_float.py
# Convert string containing decimal number
price_str = "19.99"
price_float = float(price_str)
print(price_str, type(price_str)) # Output: 19.99 <class 'str'>
print(price_float, type(price_float)) # Output: 19.99 <class 'float'>
# Strings without decimal points work too
x = float("42")
print(x, type(x)) # Output: 42.0 <class 'float'>
# Scientific notation strings work
big = float("1.5e10")
print(big) # Output: 15000000000.0Conversioni non valide:
Come int(), float() solleva un ValueError per stringhe non valide:
# invalid_float_conversion.py
# These work
print(float("3.14")) # Output: 3.14
print(float(" 2.5 ")) # Output: 2.5 (whitespace ignored)
print(float("-0.5")) # Output: -0.5
print(float("inf")) # Output: inf (infinity)
# These don't work
# print(float("hello")) # Error: ValueError
# print(float("1.2.3")) # Error: ValueErrorConvertire booleani in float:
# bool_to_float.py
print(float(True)) # Output: 1.0
print(float(False)) # Output: 0.03.7.4) Convertire in stringa con str()
La funzione str() converte qualsiasi valore nella sua rappresentazione come stringa:
Convertire numeri in stringhe:
# number_to_string.py
# Convert integer
age = 25
age_str = str(age)
print(age_str, type(age_str)) # Output: 25 <class 'str'>
# Convert float
price = 19.99
price_str = str(price)
print(price_str, type(price_str)) # Output: 19.99 <class 'str'>
# Now we can concatenate with other strings
message = "The price is $" + price_str
print(message) # Output: The price is $19.99Questo è particolarmente utile quando costruisci messaggi:
# building_messages.py
name = "Alice"
age = 25
height = 5.6
# Without str(), this would cause an error
# message = "Name: " + name + ", Age: " + age # Error!
# With str(), it works
message = "Name: " + name + ", Age: " + str(age) + ", Height: " + str(height)
print(message) # Output: Name: Alice, Age: 25, Height: 5.6Convertire booleani in stringhe:
# bool_to_string.py
is_valid = True
is_error = False
print(str(is_valid)) # Output: True
print(str(is_error)) # Output: False
# Useful in messages
status = "Status: " + str(is_valid)
print(status) # Output: Status: TrueConvertire None in stringa:
# none_to_string.py
value = None
value_str = str(value)
print(value_str) # Output: None
print(type(value_str)) # Output: <class 'str'>
# The string "None" is different from the value None
print(value is None) # Output: True
print(value_str is None) # Output: False
print(value_str == "None") # Output: True3.7.5) Schemi di conversione nella pratica
Ecco un esempio completo che mostra schemi comuni di conversione:
# conversion_patterns.py
# Get user input (always strings)
name = input("Enter your name: ")
age_str = input("Enter your age: ")
height_str = input("Enter your height in feet: ")
# Convert to appropriate types
age = int(age_str)
height = float(height_str)
# Perform calculations
age_in_months = age * 12
height_in_inches = height * 12
# Convert back to strings for output
print("Hello, " + name + "!")
print("You are " + str(age_in_months) + " months old.")
print("Your height is " + str(height_in_inches) + " inches.")
# Alternative: use multiple arguments to print() (no conversion needed)
print("Hello,", name + "!")
print("You are", age_in_months, "months old.")
print("Your height is", height_in_inches, "inches.")
# When user enters "Alice", "25", and "5.5":
# Output: Hello, Alice!
# Output: You are 300 months old.
# Output: Your height is 66.0 inches.
# Output: Hello, Alice!
# Output: You are 300 months old.
# Output: Your height is 66.0 inches.Nota come print() con argomenti multipli (separati da virgole) converta automaticamente i valori in stringhe e aggiunga spazi tra di essi. Spesso è più comodo rispetto alla conversione manuale e alla concatenazione.
3.7.6) Diagramma di flusso delle conversioni
Ecco una rappresentazione visiva delle conversioni di tipo più comuni:
Punti chiave sulle conversioni:
- int → float: sempre sicura, aggiunge
.0 - float → int: tronca la parte decimale (non arrotonda)
- Qualsiasi tipo → str: sempre sicuro, converte nella rappresentazione testuale
- str → int/float: funziona solo se la stringa rappresenta un numero valido
- bool → int/float: True diventa 1/1.0, False diventa 0/0.0
3.7.7) Errori comuni nella conversione
Ecco alcuni errori comuni che i principianti commettono con la conversione di tipo:
Errore 1: dimenticare di convertire l’input dell’utente
# conversion_mistake1.py
# Wrong: trying to do math with string
age = input("Enter your age: ")
# next_year = age + 1 # Error: TypeError
# Right: convert first
age = int(input("Enter your age: "))
next_year = age + 1
print("Next year:", next_year)Errore 2: convertire quando non è necessario
# conversion_mistake2.py
# Unnecessary: print() handles conversion automatically
age = 25
print("Age:", age) # This works fine
# No need for:
print("Age:", str(age)) # Unnecessary str() conversionErrore 3: provare a convertire stringhe non valide
# conversion_mistake3.py
# This will crash if user enters non-numeric input
# age = int(input("Enter your age: ")) # Crashes on "twenty"
# We'll learn to handle this safely in Chapter 27Errore 4: aspettarsi che int() arrotondi
# conversion_mistake4.py
# Wrong expectation: int() truncates, doesn't round
x = int(3.7)
print(x) # Output: 3 (not 4!)
# If you want rounding, use round()
x = round(3.7)
print(x) # Output: 43.8) Ottenere rappresentazioni stringa con str() e repr()
3.8.1) La differenza tra str() e repr()
Python fornisce due modi per ottenere una rappresentazione testuale (stringa) di un oggetto: str() e repr(). Anche se possono sembrare simili, servono a scopi diversi:
- str(): crea una rappresentazione “gradevole”, leggibile per gli esseri umani
- repr(): crea una rappresentazione “ufficiale”, non ambigua, pensata per gli sviluppatori
Per tipi semplici come i numeri, spesso sono uguali, ma per altri tipi possono differire sensibilmente:
# str_vs_repr.py
# For numbers, they're usually the same
x = 42
print(str(x)) # Output: 42
print(repr(x)) # Output: 42
# For strings, they differ
text = "Hello"
print(str(text)) # Output: Hello
print(repr(text)) # Output: 'Hello' (includes quotes!)
# For strings with special characters, repr() shows escape sequences
message = "Hello\nWorld"
print(str(message)) # Output: Hello
# World (newline is interpreted)
print(repr(message)) # Output: 'Hello\nWorld' (shows the \n literally)3.8.2) Quando usare str()
Usa str() quando vuoi una rappresentazione leggibile pensata per l’utente finale:
# using_str.py
price = 19.99
quantity = 3
# Create user-friendly messages
message = "Total: $" + str(price * quantity)
print(message) # Output: Total: $59.97
# str() is what print() uses automatically
print("Total: $", price * quantity) # Output: Total: $ 59.97La funzione str() è progettata per produrre un output che abbia senso per gli esseri umani, anche se può perdere un po’ di precisione tecnica. Quando chiami print(), Python usa automaticamente str() sui valori che gli passi.
3.8.3) Quando usare repr()
Usa repr() quando hai bisogno di una rappresentazione non ambigua, tipicamente per il debugging:
# using_repr.py
# Debugging: see exactly what's in a variable
text = "Hello\nWorld"
print("Debug info:", repr(text)) # Output: Debug info: 'Hello\nWorld'
# Compare two similar-looking strings
str1 = "42"
str2 = "42 " # Has trailing space
print(str1) # Output: 42
print(str2) # Output: 42 (space not obvious)
print(repr(str1)) # Output: '42'
print(repr(str2)) # Output: '42 ' (space is visible!)La funzione repr() è progettata per mostrarti esattamente ciò che Python vede, inclusi dettagli che potrebbero non essere visibili nell’output normale. Questo la rende preziosa per il debugging.
3.8.4) L’obiettivo di repr(): rappresentazioni ricreabili
Idealmente, repr() dovrebbe produrre una stringa che, se passata all’interprete di Python, ricreerebbe l’oggetto originale. Per i tipi di base, questo funziona:
# repr_recreate.py
# For numbers
x = 42
x_repr = repr(x)
print(x_repr) # Output: 42
# You could use this to recreate x
x_recreated = eval(x_repr) # eval() evaluates a string as Python code
print(x_recreated) # Output: 42
# For strings
text = "Hello"
text_repr = repr(text)
print(text_repr) # Output: 'Hello'
# This could recreate the string
text_recreated = eval(text_repr)
print(text_recreated) # Output: HelloNota importante: La funzione eval() valuta una stringa come codice Python. La menzioniamo qui per spiegare lo scopo di repr(), ma non usare mai eval() su input non fidati—è un rischio per la sicurezza. Discuteremo alternative più sicure nei capitoli successivi.
3.8.5) Esempi pratici di str() e repr()
Esempio 1: fare debugging di problemi con le stringhe
# debugging_strings.py
# User input might have unexpected whitespace
user_input = " Alice "
print("User entered:", user_input) # Output: User entered: Alice
print("Debug view:", repr(user_input)) # Output: Debug view: ' Alice '
# Now the extra spaces are obvious!
cleaned = user_input.strip() # Remove leading/trailing whitespace
print("Cleaned:", repr(cleaned)) # Output: Cleaned: 'Alice'Esempio 2: confrontare tipi diversi
# comparing_types.py
# These look similar but are different
num = 42
text = "42"
print("Number:", num) # Output: Number: 42
print("Text:", text) # Output: Text: 42
print("Number repr:", repr(num)) # Output: Number repr: 42
print("Text repr:", repr(text)) # Output: Text repr: '42'
# repr() makes the difference clear
print("Are they equal?", num == text) # Output: Are they equal? False3.8.6) str() e repr() con altri tipi
Vediamo come str() e repr() funzionano con i tipi che abbiamo imparato:
# str_repr_types.py
# Integers
x = 42
print("int str:", str(x)) # Output: int str: 42
print("int repr:", repr(x)) # Output: int repr: 42
# Floats
y = 3.14159
print("float str:", str(y)) # Output: float str: 3.14159
print("float repr:", repr(y)) # Output: float repr: 3.14159
# Booleans
b = True
print("bool str:", str(b)) # Output: bool str: True
print("bool repr:", repr(b)) # Output: bool repr: True
# None
n = None
print("None str:", str(n)) # Output: None str: None
print("None repr:", repr(n)) # Output: None repr: None
# Strings (where they differ most)
s = "Hello\nWorld"
print("string str:", str(s)) # Output: string str: Hello
# World
print("string repr:", repr(s)) # Output: string repr: 'Hello\nWorld'3.8.7) Punti chiave
Usa str() quando:
- Crei output per gli utenti finali
- Costruisci messaggi rivolti all’utente
- Formatti dati per la visualizzazione
- Vuoi un output leggibile e “amichevole”
Usa repr() quando:
- Fai debugging del codice
- Registri informazioni tecniche (logging)
- Hai bisogno di vedere esattamente cosa c’è in una variabile
- Vuoi rappresentazioni non ambigue
Ricorda:
print()usa automaticamentestr()sui suoi argomenti- Per la maggior parte dei tipi base,
str()erepr()danno risultati simili - Per le stringhe,
repr()include le virgolette e mostra le sequenze di escape repr()è progettato per essere non ambiguo e (idealmente) ricreabile
Riepilogo del capitolo
In questo capitolo hai imparato i concetti fondamentali delle variabili e dei tipi di dati in Python. Ricapitoliamo i punti chiave:
Variabili:
- Le variabili sono nomi che si riferiscono a valori in memoria
- Si creano usando l’assegnazione:
variable_name = value - Possono essere riassegnate a nuovi valori in qualsiasi momento
- Devono seguire regole di denominazione e dovrebbero seguire le convenzioni
- Usa nomi descrittivi per rendere il codice autoesplicativo
Tipi di dati:
- Ogni valore in Python ha un tipo
- Usa
type()per controllare il tipo di un valore - Python è dinamicamente tipizzato: le variabili possono riferirsi a tipi diversi in momenti diversi
- Tipi diversi supportano operazioni diverse
I tipi di base:
- int: numeri interi (positivi, negativi o zero), dimensione arbitraria
- float: numeri con la virgola, possono avere limitazioni di precisione
- str: testo racchiuso tra virgolette (singole o doppie)
- bool: valori logici
TrueoFalse - None: valore speciale che rappresenta l’assenza di un valore
Conversione di tipo:
int(): converte in intero (tronca i float, interpreta le stringhe)float(): converte in numero a virgola mobilestr(): converte in stringa (funziona sempre)- Le conversioni possono fallire con input non validi (solleva
ValueError)
Rappresentazioni stringa:
str(): rappresentazione leggibile per gli utenti finalirepr(): rappresentazione non ambigua per sviluppatori/debuggingprint()usastr()automaticamente
Questi concetti costituiscono le fondamenta di tutto il resto in Python. Ogni programma che scriverai userà variabili per memorizzare dati, e capire i tipi di dati ti aiuta a prevedere quali operazioni funzioneranno e quali errori potrebbero verificarsi.
Nel prossimo capitolo costruiremo su queste basi esplorando in dettaglio come lavorare con i numeri, incluse le operazioni aritmetiche, la precedenza degli operatori e gli schemi numerici più comuni. Imparerai come eseguire calcoli, usare funzioni matematiche e gestire le particolarità dell’aritmetica in virgola mobile.