Impara Python in 10 minuti
Python è un linguaggio di programmazione di alto livello e interpretato, noto per la sua sintassi concisa e le sue potenti funzionalità. Questo tutorial si basa sull’ultima versione di Python 3.13+, aiutandoti a imparare Python rapidamente.
1. Scrivere il tuo primo programma Python
Iniziamo con un programma semplice. Crea un file chiamato hello.py
e inserisci il seguente codice:
print("Ciao, Mondo!")
Salva il file ed esegui il seguente comando nel terminale o nella riga di comando:
python hello.py
L’output sarà:
Ciao, Mondo!
Questo semplice programma dimostra la funzionalità di output di base di Python. La funzione print()
viene utilizzata per visualizzare informazioni testuali nella console.
2. Sintassi di base
La sintassi di Python è semplice e facile da comprendere. Python utilizza l’indentazione per definire i blocchi di codice, a differenza di altri linguaggi che usano parentesi graffe {}
.
# Questo è un commento
print("Ciao, Mondo!")
Regole di sintassi di base in Python:
- Indentazione: Per impostazione predefinita, si usano 4 spazi per indicare il livello di un blocco di codice. Ad esempio, il codice all’interno di funzioni o cicli deve essere indentato.
- Commenti: I commenti su una singola riga iniziano con
#
, mentre i commenti su più righe usano virgolette triple"""
o'''
. - Istruzioni: Di solito una istruzione per riga, non è necessario il punto e virgola
;
alla fine. - Blocchi di codice: Definiti dall’indentazione, come in
if
,for
o nei corpi delle funzioni.
Esempio con commenti su più righe:
"""
Questo è un commento su più righe,
che si estende su diverse righe.
"""
L’indentazione è una caratteristica chiave della sintassi di Python, utilizzata per definire la struttura gerarchica dei blocchi di codice:
if True:
print("Questa riga è indentata")
print("Anche questa riga è indentata")
print("Questa riga non è indentata")
3. Variabili e tipi di dati
In Python, le variabili sono contenitori per memorizzare dati. Python è un linguaggio a tipizzazione dinamica, il che significa che non è necessario dichiarare in anticipo il tipo di una variabile.
Regole di base per la denominazione delle variabili:
- I nomi delle variabili possono contenere solo lettere, numeri e trattini bassi.
- I nomi delle variabili non possono iniziare con un numero.
- I nomi delle variabili sono sensibili alle maiuscole.
- Le parole chiave di Python non possono essere usate come nomi di variabili.
Il tipo di variabile è determinato dal valore assegnato. I principali tipi di dati di base di Python sono:
- Intero (int): ad esempio,
42
o-10
, senza limite di dimensione. - Float (float): ad esempio,
3.14
o2.5e3
(notazione scientifica). - Stringa (str): ad esempio,
"ciao"
o'mondo'
, usando virgolette singole o doppie. - Booleano (bool):
True
oFalse
. - NoneType (None): Rappresentato da
None
, indica un valore nullo o assente.
Python supporta gli hint di tipo per migliorare la leggibilità del codice, utilizzati per il controllo statico e il supporto IDE, senza influenzare il comportamento in esecuzione:
name: str = "Alice"
age: int = 25
3.1 Tipi numerici (Number)
Python supporta tre tipi numerici: intero (int), float (float) e complesso (complex).
# Intero
age = 25
population = 1000000
# Float
temperature = 36.5
pi = 3.14159
# Complesso
complex_num = 3 + 4j
3.2 Stringa (String)
Le stringhe sono sequenze di caratteri, racchiuse tra virgolette singole o doppie.
single_quote = 'Stringa con virgolette singole'
double_quote = "Stringa con virgolette doppie"
multiline = """Questa è una
stringa su più righe"""
Operazioni sulle stringhe:
text = "Programmazione Python"
print(len(text)) # Lunghezza della stringa
print(text.upper()) # Converti in maiuscolo
print(text.lower()) # Converti in minuscolo
print(text[0]) # Accedi al primo carattere
print(text[2:6]) # Slicing della stringa
3.3 Tipo booleano (Boolean)
Il tipo booleano ha due valori: True
e False
.
is_active = True
is_complete = False
# Operazioni booleane
result1 = True and False # False
result2 = True or False # True
result3 = not True # False
3.4 Tipo None (None)
None
rappresenta uno stato nullo o senza valore.
value = None
if value is None:
print("Il valore è nullo")
4. Strutture dati
Python fornisce diverse strutture dati integrate per memorizzare e manipolare i dati. Di seguito sono elencate le strutture dati più comuni e il loro utilizzo.
4.1 Lista (List)
Una lista è una collezione ordinata e modificabile. Puoi aggiungere, rimuovere o modificare elementi in una lista. Le liste sono definite usando parentesi quadre []
.
numbers = [1, 2, 3, 4, 5]
numbers.append(6) # Aggiungi elemento
numbers.insert(0, 0) # Inserisci in una posizione specifica
numbers.remove(3) # Rimuovi un valore specifico
numbers[0] = 10 # Modifica elemento
print(numbers) # [10, 2, 4, 5, 6]
Slicing delle liste per accedere a sottoliste:
numbers = [10, 20, 30, 40, 50]
print(numbers[1:4]) # Output: [20, 30, 40]
print(numbers[:3]) # Output: [10, 20, 30]
print(numbers[-2:]) # Output: [40, 50]
Comprensione delle liste:
squares = [x**2 for x in range(5)]
print(squares) # [0, 1, 4, 9, 16]
even Ascoltare even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(even_squares) # [0, 4, 16, 36, 64]
4.2 Tupla (Tuple)
Una tupla è una collezione ordinata ma immutabile. Una volta creata, i suoi elementi non possono essere modificati. Le tuple sono definite usando parentesi tonde ()
. Grazie alla loro immutabilità, le tuple sono generalmente più veloci delle liste e possono essere usate come chiavi di dizionari.
point = (10, 20)
x, y = point # Unpacking
print(x, y) # Output: 10 20
Tuple con un solo elemento richiedono una virgola:
single_tuple = (42,)
4.3 Dizionario (Dict)
Un dizionario è una collezione non ordinata (ordinata in Python 3.7+) di coppie chiave-valore. Ogni chiave è unica ed è associata a un valore. I dizionari sono definiti usando parentesi graffe {}
.
student = {
"name": "John",
"age": 20,
"major": "Computer Science"
}
# Accesso e modifica del dizionario
print(student["name"])
student["age"] = 21
student["gpa"] = 3.8
# Accesso sicuro
print(student.get("phone", "Non fornito"))
# Iterazione sul dizionario
for key, value in student.items():
print(f"{key}: {value}")
Comprensione dei dizionari:
# Crea un dizionario dei quadrati
squares_dict = {x: x**2 for x in range(5)}
print(squares_dict) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# Comprensione condizionale dei dizionari
even_squares_dict = {x: x**2 for x in range(10) if x % 2 == 0}
print(even_squares_dict) # {0: 0, 2: 4, 4: 16, 6: 36, 8: 64}
4.4 Insieme (Set)
Un insieme è una collezione non ordinata senza elementi duplicati. Definito usando parentesi graffe {}
o set()
.
# Creazione di un insieme
fruits = {"apple", "banana", "orange"}
numbers = set([1, 2, 3, 3, 4, 4, 5]) # Deduplicazione automatica
print(numbers) # {1, 2, 3, 4, 5}
# Operazioni sugli insiemi
set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}
print(set1 | set2) # Unione: {1, 2, 3, 4, 5, 6}
print(set1 & set2) # Intersezione: {3, 4}
print(set1 - set2) # Differenza: {1, 2}
print(set1 ^ set2) # Differenza simmetrica: {1, 2, 5, 6}
5. Operazioni e Operatori
Python fornisce un ricco set di operatori per vari calcoli e confronti, inclusi operatori aritmetici, di confronto, logici, bitwise e di identità.
- Operatori aritmetici:
+
,-
,*
,/
,//
(divisione intera),%
(modulo),**
(esponenziazione). - Operatori di confronto:
==
,!=
,>
,<
,>=
,<=
. - Operatori logici:
and
,or
,not
. - Operatori di appartenenza:
in
,not in
. - Operatori di identità:
is
,is not
.
5.1 Operatori aritmetici
Gli operatori aritmetici sono usati per operazioni matematiche. La precedenza degli operatori segue le regole matematiche (ad esempio, **
ha una precedenza maggiore rispetto a +
o -
). Le parentesi ()
possono essere usate per cambiare la precedenza.
a, b = 10, 3
print(f"Somma: {a + b}") # 13
print(f"Sottrazione: {a - b}") # 7
print(f"Moltiplicazione: {a * b}") # 30
print(f"Divisione: {a / b}") # 3.333...
print(f"Divisione intera: {a // b}") # 3
print(f"Modulo: {a % b}") # 1
print(f"Esponenziazione: {a ** b}") # 1000
5.2 Operatori di confronto
Gli operatori di confronto confrontano due valori e restituiscono un booleano (True
o False
).
x, y = 5, 10
print(f"Uguale: {x == y}") # False
print(f"Non uguale: {x != y}") # True
print(f"Maggiore di: {x > y}") # False
print(f"Minore di: {x < y}") # True
print(f"Maggiore o uguale: {x >= y}") # False
print(f"Minore o uguale: {x <= y}") # True
5.3 Operatori logici
Gli operatori logici combinano o manipolano valori booleani (True
o False
), tipicamente usati nelle istruzioni condizionali.
a, b = True, False
print(f"Operazione AND: {a and b}") # False
print(f"Operazione OR: {a or b}") # True
print(f"Operazione NOT: {not a}") # False
5.4 Operatori di identità
L’operatore is
confronta l’identità di due oggetti, verificando se fanno riferimento allo stesso indirizzo di memoria (non solo valori uguali). Differisce da ==
, che confronta il contenuto.
list1 = [1, 2, 3]
list2 = [1, 2, 3]
list3 = list1
print(f"list1 is list2: {list1 is list2}") # False
print(f"list1 is list3: {list1 is list3}") # True
print(f"list1 == list2: {list1 == list2}") # True
5.5 Operatori di appartenenza
Gli operatori di appartenenza verificano se un valore è membro di una sequenza (ad esempio, lista, tupla, stringa, insieme), restituendo un booleano.
fruits = ["apple", "banana", "orange"]
print(f"'apple' in fruits: {'apple' in fruits}") # True
print(f"'grape' not in fruits: {'grape' not in fruits}") # True
6. Controllo del flusso
Python fornisce diverse istruzioni di controllo del flusso per gestire l’ordine di esecuzione di un programma.
6.1 Istruzioni if
L’istruzione if
valuta una condizione ed esegue il suo blocco se la condizione è True
. Usa elif
e else
per condizioni complesse.
age = 20
if age >= 18:
print("Adulto")
elif age >= 13:
print("Adolescente")
else:
print("Bambino")
6.2 Cicli for
Il ciclo for
itera su un oggetto iterabile (ad esempio, lista, tupla, stringa o range).
# Iterazione su una lista
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)
# Utilizzo di range() per il ciclo
for i in range(5):
print(i) # Output: 0, 1, 2, 3, 4
6.3 Cicli while
Il ciclo while
continua a eseguire un blocco fintanto che la sua condizione rimane True
.
count = 0
while count < 5:
print(count)
count += 1
- break e continue:
break
esce dal ciclo,continue
salta l’iterazione corrente.
for i in range(10):
if i == 5:
break
if i % 2 == 0:
continue
print(i) # Output: 1, 3
6.4 Istruzioni match
Introdotte in Python 3.10, le istruzioni match
forniscono un potente pattern matching strutturale, agendo come alternativa avanzata alle catene if/elif/else
.
http_status = 200
match http_status:
case 200 | 201:
print("Successo")
case 404:
print("Non trovato")
case 500:
print("Errore del server")
case _: # Wildcard, corrisponde a qualsiasi altro caso
print("Stato sconosciuto")
7. Input e Output
7.1 Input e Output di base
Usa la funzione input()
per ottenere input dall’utente e la funzione print()
per visualizzare informazioni.
# Ottenere input dall'utente
name = input("Inserisci il tuo nome: ")
age = int(input("Inserisci la tua età: "))
# Visualizzare informazioni
print("Benvenuto", name)
print("Hai", age, "anni")
7.2 Output formattato (f-strings)
Introdotte in Python 3.6+, le f-strings (stringhe letterali formattate) sono un modo comodo e potente per formattare le stringhe. Prefissa una stringa con f
o F
e incorpora variabili o espressioni tra parentesi graffe {}
.
user = "Alice"
items = 3
total_cost = 45.5
# Utilizzo di f-string per un messaggio formattato
message = f"L'utente {user} ha acquistato {items} articoli per ${total_cost:.2f}."
print(message)
# Espressioni nelle f-strings
print(f"2 + 3 equivale a {2 + 3}")
Espressioni e chiamate di funzione nelle f-strings:
width = 10
height = 5
# Utilizzo di espressioni nelle f-strings
area = f"Area del rettangolo: {width * height}"
print(area)
# Chiamata di funzioni
text = "python"
formatted = f"Maiuscolo: {text.upper()}, Lunghezza: {len(text)}"
print(formatted)
Opzioni di formattazione nelle f-strings:
pi = 3.14159265359
large_number = 1234567
# Formattazione dei numeri
print(f"Pi (2 decimali): {pi:.2f}")
print(f"Pi (4 decimali): {pi:.4f}")
print(f"Numero grande (migliaia): {large_number:,}")
print(f"Percentuale: {0.85:.1%}")
# Allineamento delle stringhe
name = "Python"
print(f"Allineamento a sinistra: '{name:<10}'")
print(f"Allineamento a destra: '{name:>10}'")
print(f"Allineamento al centro: '{name:^10}'")
Formattazione di data e ora con f-strings:
from datetime import datetime
now = datetime.now()
print(f"Ora corrente: {now}")
print(f"Ora formattata: {now:%Y-%m-%d %H:%M:%S}")
print(f"Solo data: {now:%Y-%m-%d}")
9. Funzioni
Le funzioni in Python sono blocchi di codice riutilizzabili per attività specifiche, definite usando la parola chiave def
, che supportano parametri predefiniti, argomenti variabili e argomenti con nome.
Definizione di base di una funzione:
def greet(name):
"""Funzione di saluto"""
return f"Ciao, {name}!"
# Chiamata della funzione
message = greet("John")
print(message)
Argomenti con nome:
Gli argomenti con nome vengono passati usando la sintassi nome_parametro=valore
.
def greet(name, greeting="Ciao"):
return f"{greeting}, {name}!"
print(greet("Alice")) # Output: Ciao, Alice!
print(greet("Bob", "Salve")) # Output: Salve, Bob!
Argomenti variabili:
Gli argomenti variabili consentono alle funzioni di accettare un numero arbitrario di argomenti, sia posizionali (*args
) che con nome (**kwargs
).
# Argomenti posizionali variabili (*args)
def sum_numbers(*args):
return sum(args)
print(sum_numbers(1, 2, 3, 4)) # Output: 10
# Argomenti con nome variabili (**kwargs)
def print_kwargs(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
print_kwargs(name="Alice", age=25, city="Pechino")
Annotazioni di funzione:
Le annotazioni di funzione aggiungono metadati descrittivi ai parametri e ai valori di ritorno delle funzioni, migliorando leggibilità e documentazione.
def calculate_area(length: float, width: float) -> float:
"""Calcola l'area del rettangolo"""
return length * width
def process_user(name: str, age: int, active: bool = True) -> dict:
"""Elabora le informazioni dell'utente"""
return {
"name": name,
"age": age,
"active": active
}
10. Espressioni Lambda
Le espressioni lambda creano funzioni anonime, fornendo un modo conciso per definire piccole funzioni.
square = lambda x: x ** 2
print(square(5)) # Output: 25
Comunemente usate con funzioni di ordine superiore come map
o filter
:
numbers = [1, 2, 3, 4]
squares = list(map(lambda x: x ** 2, numbers))
print(squares) # Output: [1, 4, 9, 16]
11. Classi e Oggetti
Python supporta la programmazione orientata agli oggetti usando la parola chiave class
:
class Person:
"""Classe Persona"""
def __init__(self, name, age):
"""Costruttore"""
self.name = name
self.age = age
def introduce(self):
"""Metodo di introduzione"""
return f"Sono {self.name}, ho {self.age} anni"
def have_birthday(self):
"""Metodo del compleanno"""
self.age += 1
return f"{self.name} ha compiuto gli anni, ora ha {self.age} anni"
# Creazione di oggetti
person1 = Person("John", 25)
person2 = Person("Jane", 30)
print(person1.introduce())
print(person2.have_birthday())
11.1 Attributi di classe e di istanza
In Python, gli attributi di classe e di istanza sono due tipi di attributi per memorizzare dati nelle classi e negli oggetti.
- Attributi di classe: Definiti fuori dai metodi, appartengono alla classe stessa e sono condivisi tra tutte le istanze.
- Attributi di istanza: Definiti nei metodi (di solito
__init__
), legati a istanze specifiche tramiteself
.
class Student:
# Attributi di classe
school = "Stanford University"
student_count = 0
def __init__(self, name, major):
# Attributi di istanza
self.name = name
self.major = major
Student.student_count += 1
@classmethod
def get_student_count(cls):
"""Metodo di classe"""
return cls.student_count
@staticmethod
def is_valid_age(age):
"""Metodo statico"""
return 0 < age < 150
# Esempio di utilizzo
student1 = Student("John", "Computer Science")
student2 = Student("Jane", "Matematica")
print(f"Scuola: {Student.school}")
print(f"Totale studenti: {Student.get_student_count()}")
print(f"Età valida: {Student.is_valid_age(20)}")
11.2 Ereditarietà di classe
L’ereditarietà consente a una classe (sottoclasse) di ereditare attributi e metodi da un’altra classe (classe genitore), permettendo il riutilizzo e l’estensione del codice.
class Animal:
def __init__(self, name, species):
self.name = name
self.species = species
def make_sound(self):
return f"{self.name} emette un suono"
def info(self):
return f"{self.name} è un {self.species}"
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name, "Dog")
self.breed = breed
def make_sound(self):
return f"{self.name} abbaia"
def fetch(self):
return f"{self.name} riporta la palla"
class Cat(Animal):
def __init__(self, name, color):
super().__init__(name, "Cat")
self.color = color
def make_sound(self):
return f"{self.name} miagola"
def climb(self):
return f"{self.name} si arrampica su un albero"
# Utilizzo dell'ereditarietà
dog = Dog("Buddy", "Golden Retriever")
cat = Cat("Mimi", "Arancione")
print(dog.info())
print(dog.make_sound())
print(dog.fetch())
print(cat.info())
print(cat.make_sound())
print(cat.climb())
11.3 Metodi speciali (Metodi magici)
I metodi speciali (o metodi magici) sono metodi con doppio underscore che definiscono comportamenti specifici, chiamati automaticamente da Python in determinati scenari.
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def __str__(self):
"""Rappresentazione come stringa"""
return f"Rettangolo({self.width}x{self.height})"
def __repr__(self):
"""Rappresentazione ufficiale come stringa"""
return f"Rettangolo(width={self.width}, height={self.height})"
def __eq__(self, other):
"""Confronto di uguaglianza"""
if isinstance(other, Rectangle):
return self.width == other.width and self.height == other.height
return False
def __lt__(self, other):
"""Confronto minore di (per area)"""
if isinstance(other, Rectangle):
return self.area() < other.area()
return NotImplemented
def __add__(self, other):
"""Operazione di somma"""
if isinstance(other, Rectangle):
return Rectangle(self.width + other.width, self.height + other.height)
return NotImplemented
def area(self):
"""Calcola l'area"""
return self.width * self.height
# Utilizzo dei metodi speciali
rect1 = Rectangle(3, 4)
rect2 = Rectangle(5, 6)
rect3 = Rectangle(3, 4)
print(rect1) # Rettangolo(3x4)
print(repr(rect1)) # Rettangolo(width=3, height=4)
print(rect1 == rect3) # True
print(rect1 < rect2) # True
print(rect1 + rect2) # Rettangolo(8x10)
12. Gestori di contesto
I gestori di contesto garantiscono l’acquisizione e il rilascio corretto delle risorse, comunemente usati con l’istruzione with
per la gestione delle risorse, come file o connessioni a database.
12.1 Utilizzo dei gestori di contesto
Le operazioni sui file sono un caso d’uso comune per i gestori di contesto:
with open("example.txt", "r") as file:
content = file.read()
print(content)
L’istruzione with
garantisce che il file venga chiuso automaticamente dopo le operazioni.
12.2 Gestori di contesto personalizzati
Crea gestori di contesto personalizzati definendo i metodi __enter__
e __exit__
:
class DatabaseConnection:
def __init__(self, database_name):
self.database_name = database_name
self.connection = None
def __enter__(self):
"""Chiamato all'ingresso nel contesto"""
print(f"Connessione al database: {self.database_name}")
self.connection = f"Connessione a {self.database_name}"
return self.connection
def __exit__(self, exc_type, exc_value, traceback):
"""Chiamato all'uscita dal contesto"""
print(f"Chiusura della connessione al database: {self.database_name}")
if exc_type:
print(f"Si è verificata un'eccezione: {exc_type.__name__}: {exc_value}")
self.connection = None
return False # Non sopprime le eccezioni
# Utilizzo del gestore di contesto personalizzato
with DatabaseConnection("user_database") as conn:
print(f"Uso della connessione: {conn}")
print("Esecuzione delle operazioni sul database...")
Utilizzo del modulo contextlib
per creare gestori di contesto:
from contextlib import contextmanager
import time
@contextmanager
def timer(operation_name):
"""Gestore di contesto per il timer"""
print(f"Inizio {operation_name}")
start_time = time.time()
try:
yield
finally:
end_time = time.time()
print(f"{operation_name} completato in {end_time - start_time:.2f} secondi")
# Utilizzo del gestore di contesto basato su decoratore
with timer("elaborazione dati"):
# Simulazione di un'operazione lunga
time.sleep(1)
print("Elaborazione dati...")
13. Gestione delle eccezioni
La gestione delle eccezioni garantisce la robustezza del programma, usando try
, except
, else
e finally
per gestire le eccezioni.
try:
result = 10 / 0
except ZeroDivisionError:
print("Impossibile dividere per zero!")
else:
print("Divisione riuscita")
finally:
print("Questo viene sempre eseguito")
Output:
Impossibile dividere per zero!
Questo viene sempre eseguito
14. Operazioni sui file
Python fornisce metodi semplici per leggere e scrivere file, tipicamente usati con i gestori di contesto.
14.1 Lettura dei file
Lettura del contenuto di un file di testo:
with open("example.txt", "r") as file:
content = file.read()
print(content)
Lettura riga per riga:
with open("example.txt", "r") as file:
for line in file:
print(line.strip())
14.2 Scrittura sui file
Scrittura su un file di testo:
with open("output.txt", "w") as file:
file.write("Ciao, Python!\n")
Aggiunta di contenuto:
with open("output.txt", "a") as file:
file.write("Aggiunta di nuovo contenuto.\n")
15. Moduli e Pacchetti
I moduli sono file contenenti codice Python, e i pacchetti sono directory contenenti più moduli. Importa i moduli usando import
:
import math
print(math.sqrt(16)) # Output: 4.0
Esempio di modulo personalizzato (supponiamo che il file sia chiamato mymodule.py
):
# mymodule.py
def say_hello():
return "Ciao dal modulo!"
Importazione e utilizzo:
import mymodule
print(mymodule.say_hello()) # Output: Ciao dal modulo!
16. Ambito e Namespace
16.1 Ambito
L’ambito definisce la regione in cui una variabile è accessibile. Python segue la regola LEGB per la ricerca delle variabili:
- L (Locale): All’interno di una funzione o metodo di classe.
- E (Enclosing): Nella funzione esterna di una funzione annidata (closure).
- G (Globale): A livello di modulo.
- B (Built-in): Funzioni ed eccezioni incorporate come
print()
olen()
.
x = "x globale"
def outer_func():
x = "x enclosing"
def inner_func():
x = "x locale"
print(x) # Accede all'ambito locale x
inner_func()
print(x) # Accede all'ambito enclosing x
outer_func()
print(x) # Accede all'ambito globale x
Utilizzo di global
o nonlocal
per modificare le variabili dell’ambito:
x = "globale"
def modify_global():
global x
x = "modificato"
modify_global()
print(x) # Output: modificato
16.2 Namespace
Un namespace è una mappatura da nomi a oggetti, come un dizionario in cui le chiavi sono i nomi delle variabili e i valori sono gli oggetti.
Ogni modulo, funzione e classe ha il proprio namespace, prevenendo conflitti di nomi. Usa globals()
e locals()
per ispezionare i namespace.
a_variable = 10
def some_function():
b_variable = 20
# locals() restituisce il dizionario del namespace locale corrente
print(f"Locali: {locals()}")
print(f"Globali: {globals().keys()}") # Stampa le chiavi del namespace globale
some_function()
17. Generatori
I generatori sono iteratori speciali che generano valori su richiesta, invece di creare tutti i valori contemporaneamente, rendendoli efficienti in termini di memoria per grandi set di dati.
I generatori usano la parola chiave yield
per restituire valori in modo pigro:
def fibonacci(n):
a, b = 0, 1
for _ in range(n):
yield a
a, b = b, a + b
for num in fibonacci(5):
print(num) # Output: 0, 1, 1, 2, 3
18. Multithreading
Il multithreading consente a un programma di eseguire più operazioni contemporaneamente, utile per attività legate all’I/O come richieste di rete o operazioni sui file.
Il modulo threading
di Python fornisce strumenti per creare e gestire thread. A causa del Global Interpreter Lock (GIL), il multithreading non raggiunge un vero parallelismo CPU in un singolo processo, ma migliora significativamente le prestazioni per attività legate all’I/O.
import threading
import time
def worker(thread_name):
print(f"Thread {thread_name} in avvio...")
time.sleep(2) # Simula un'operazione lunga
print(f"Thread {thread_name} terminato.")
# Crea i thread
thread1 = threading.Thread(target=worker, args=("A",))
thread2 = threading.Thread(target=worker, args=("B",))
# Avvia i thread
thread1.start()
thread2.start()
# Aspetta che tutti i thread completino
thread1.join()
thread2.join()
print("Tutti i thread completati.")
19. Programmazione asincrona
La programmazione asincrona è ideale per scenari ad alto I/O e alta concorrenza, usando un ciclo di eventi per gestire le attività invece dei thread.
Python supporta la programmazione asincrona tramite la libreria asyncio
e la sintassi async/await
.
async def
: Definisce una coroutine.await
: Mette in pausa l’esecuzione della coroutine, aspettando che un oggetto awaitable completi.
import asyncio
async def say_hello():
print("Ciao")
await asyncio.sleep(1) # Sleep non bloccante, simula I/O
print("Mondo")
async def main():
# Crea e aspetta un'attività
await asyncio.create_task(say_hello())
# Esegue la coroutine principale
asyncio.run(main())
Output:
Ciao
Mondo