Corso
Le competenze di programmazione in Python sono diventate sempre più richieste negli ultimi anni. Per aiutarti a svilupparle, abbiamo raccolto 30 trucchi Python che puoi usare per migliorare il tuo codice. Provane uno al giorno per i prossimi 30 giorni e dai un'occhiata al nostro post sulle best practice Python per assicurarti che il tuo codice sia di altissimo livello.
Se le tue abilità in Python non sono ancora al top, puoi affilarle con il nostro Percorso di competenze Python.
Trucchi su sequenze e strutture dati
#1 Slicing
a = "Hello World!"
print(a[::-1])
"""
!dlroW olleH
"""
Lo slicing è una funzionalità di Python basata sull'indicizzazione che permette di accedere a un sottoinsieme di una sequenza. Un indice è semplicemente la posizione di un elemento nella sequenza. Se il tipo di sequenza è mutabile, puoi usare lo slicing per estrarre e modificare i dati.
Nota: Possiamo usare lo slicing anche su una sequenza immutabile, ma tentarne la modifica genererà un TypeError.
Il formato con cui si implementano gli slice è: sequence[start:stop:step]. Se non specifichi valori per i parametri start, stop e step, verranno usati i valori predefiniti. I default sono:
- "start" predefinito a 0
- "stop" predefinito alla lunghezza della sequenza
- "step" predefinito a 1 se non specificato.
Con sequence[start:stop] gli elementi restituiti vanno dall'indice di partenza fino a stop - 1 (lo stop non è incluso).
Possiamo anche passare indici negativi, utili ad esempio per invertire la sequenza. In una lista di 4 elementi, l'indice 0 è anche -4 e l'ultimo indice è anche -1. Nell'esempio sopra, questa logica è stata applicata al parametro step della sequenza. Di conseguenza, la stringa è stata stampata al contrario, partendo dalla fine fino all'indice 0.
#2 Scambio in place / assegnazione simultanea
a = 10
b = 5
print(f"First: {a, b}")
"""
First: (10, 5)
"""
a, b = b, a + 2
print(f"Second: {a, b}")
"""
Second: (5, 12)
"""
Se la tua prima impressione era che il valore di b sarebbe stato 7 invece di 12, sei caduto nella trappola dello scambio in place.
In Python, possiamo decomprimere gli iterabili in variabili con una singola assegnazione usando l'unpacking automatico. Per esempio:
a, b, c = [1, 2, 3]
print(a)
print(b)
print(c)
"""
1
2
3
"""
Possiamo anche raccogliere più valori in una singola variabile usando * – questo trucco Python si chiama packing. Ecco un esempio di packing.
a, *b = 1, 2, 3
print(a, b)
"""
1 [2, 3]
"""
Combinando packing e unpacking automatici nasce la tecnica nota come assegnazione simultanea. Possiamo usarla per assegnare una serie di valori a una serie di variabili.
#3 Liste vs. tuple
import sys
a = [1, 2, 3, 4, 5]
b = (1, 2, 3, 4, 5)
print(f"List size: {sys.getsizeof(a)} bytes")
print(f"Tuple size: {sys.getsizeof(b)} bytes")
"""
List size: 52 bytes
Tuple size: 40 bytes
"""
La maggior parte dei programmatori Python conosce la struttura dati lista. Lo stesso non si può dire delle tuple. Entrambe sono iterabili, consentono l'indicizzazione e permettono di memorizzare tipi eterogenei. Ma ci sono situazioni in cui l'uso di una tupla può essere preferibile a una lista.
Prima di tutto, le liste sono mutabili, quindi possiamo modificarle a piacere:
a = [1,2,3,4,5]
a[2] = 8
print(a)
"""
[1,2,8,4,5]
"""
Le tuple, invece, sono immutabili: tentare di modificarle genererà un TypeError.
Per questo motivo, le tuple sono più efficienti in memoria: Python può allocare esattamente il blocco necessario ai dati. Al contrario, in una lista va allocata memoria extra nel caso venga estesa: si chiama allocazione dinamica della memoria.
In breve: quando non vuoi che i dati vengano modificati, per ragioni di memoria è preferibile una tupla a una lista. Le tuple sono anche più veloci delle liste.
Scopri di più sulle strutture dati in Python in questo tutorial.
#4 Generator
a = [x * 2 for x in range(10)]
b = (x * 2 for x in range(10))
print(a)
print(b)
"""
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
<generator object <genexpr> at 0x7f61f8808b50>
"""
Le list comprehension sono il modo più "pythonic" per creare una lista da un altro iterabile: sono molto più veloci di un ciclo for. Ma cosa succede se cambi per sbaglio le parentesi da [] a ()? Ottieni un oggetto generator.
In Python, le parentesi tonde con la logica da list comprehension creano un oggetto generator. I generator sono un tipo speciale di iterabile. A differenza delle liste, non memorizzano gli elementi: conservano invece le istruzioni per generare ogni elemento in ordine e lo stato corrente dell'iterazione.
Ogni elemento viene generato solo su richiesta usando la valutazione pigra. Il vantaggio principale di questo trucco con i generator è un minore uso di memoria, perché l'intera sequenza non viene costruita in una volta sola.
#5 Aliasing
a = [1, 2, 3, 4 ,5]
b = a
# Change the 4th index in b
b[4] = 7
print(id(a))
print(id(b))
print(a) # Remember we did not explicitly make changes to a.
"""
15136008
15136008
[1, 2, 3, 4, 7]
"""
Python è un linguaggio orientato agli oggetti: tutto è un oggetto. Quindi assegnare un oggetto a un identificatore significa creare un riferimento a quell'oggetto.
Quando assegniamo un identificatore a un altro, otteniamo due identificatori che fanno riferimento allo stesso oggetto. Questo concetto è detto aliasing. Le modifiche in un alias influenzeranno l'altro. A volte è voluto, ma spesso ci coglie di sorpresa.
Un modo per evitarlo è non creare alias quando si usano oggetti mutabili. Un'altra soluzione è creare un clone dell'oggetto originale invece di un riferimento.
Il modo più semplice per clonare è sfruttare lo slicing:
b = a[:]
Questo creerà un nuovo riferimento a un oggetto lista nell'identificatore b.
Puoi anche usare altre soluzioni, come chiamare list(a) quando assegni i dati a un altro identificatore o usare il metodo copy().
#6 L'operatore ‘not’
a = []
print(not a)
"""
True
"""
Il modo più semplice per controllare se una struttura dati è vuota è usare l'operatore not. Il not integrato di Python è un operatore logico che restituisce True se l'espressione non è vera, altrimenti restituisce False: inverte il valore di verità di espressioni e oggetti booleani.
Un altro modo in cui potresti vederlo è in un'istruzione if:
if not a:
# do something...
Quando a è True, l'operatore not restituirà False, e viceversa.
All'inizio può essere controintuitivo: prova a farci la mano.
Trucchi su stringhe e output
#7 F-string
first_name = "John"
age = 19
print(f"Hi, I'm {first_name} and I'm {age} years old!")
"""
Hi, I'm John and I'm 19 years old!
"""
A volte dobbiamo formattare una stringa; Python 3.6 ha introdotto una funzione comodissima chiamata f-string per semplificare il processo. Per apprezzarla meglio, aiuta capire come si formattavano le stringhe prima di questa versione.
Ecco come si faceva:
first_name = "John"
age = 19
print("Hi, I'm {} and I'm {} years old!".format(first_name, age))
"""
Hi, I'm John and I'm 19 years old!
"""
In sostanza, il nuovo metodo è più veloce, più leggibile, più conciso e meno incline a errori.
Un altro uso delle f-string è stampare il nome dell'identificatore insieme al valore. Questa funzionalità è stata introdotta in Python 3.8.
x = 10
y = 20
print(f"{x = }, {y = }")
"""
x = 10, y = 20
"""
Dai un'occhiata a questo tutorial su formattazione con f-string in Python per saperne di più.
#8 Il parametro ‘end’ di print()
languages = ["english", "french", "spanish", "german", "twi"]
print(' '.join(languages))
"""
english french spanish german twi
"""
È piuttosto comune usare print senza definire i parametri opzionali. Di conseguenza, molti Pythonisti non sanno che puoi controllarne in parte l'output.
Un parametro opzionale che possiamo cambiare è end. Il parametro end specifica cosa mostrare alla fine di una chiamata a print.
Il valore predefinito di end è "\n", che dice a Python di andare a capo. Nel codice sopra l'abbiamo cambiato in uno spazio. Così tutti gli elementi della lista vengono stampati sulla stessa riga.
#9 Aggiungere a una tupla
a = (1, 2, [1, 2, 3])
a[2].append(4)
print(a)
"""
(1, 2, [1, 2, 3, 4])
"""
Sappiamo già che le tuple sono immutabili – vedi trucco Python #3 Liste vs. tuple. Tentare di cambiarne lo stato genererebbe un TypeError. Ma se pensi a una tupla come a una sequenza di nomi con associazioni a oggetti che non possono essere cambiate, potresti vederla diversamente.
I primi due elementi della tupla sono interi, quindi immutabili. L'ultimo elemento è una lista, che in Python è mutabile.
Se consideriamo la lista come un altro nome nella sequenza, associato a un oggetto che non può essere cambiato, ci rendiamo conto che la lista può comunque essere modificata dall'interno della tupla.
Lo consiglieremmo in pratica? Probabilmente no, ma è una curiosità utile!
#10 Unire dizionari
a = {"a": 1, "b": 2}
b = {"c": 3, "d": 4}
a_and_b = a | b
print(a_and_b)
"""
{"a": 1, "b": 2, "c": 3, "d": 4}
"""
In Python 3.9 e successivi, è possibile unire dizionari usando | (OR bit a bit). Non c'è molto altro da dire su questo trucco, se non che è molto più leggibile!
Trucchi di stile e sintassi
#11 Operatore ternario / espressioni condizionali
condition = True
name = "John" if condition else "Doe"
print(name)
"""
John
"""
Nel codice sopra vedi il cosiddetto operatore ternario, noto anche come espressione condizionale. Lo usiamo per valutare qualcosa in base al fatto che una condizione sia True o False.
Avremmo potuto scrivere il codice anche così:
condition = True
if condition:
name = "John"
else:
name = "Doe"
print(name)
"""
John
"""
Anche se il risultato non cambia, nota come il ternario ci permetta di scrivere codice più corto e chiaro. È quello che i Pythonisti chiamano il modo più "Pythonic" di scrivere.
#12 Rimuovere duplicati dalle liste
a = [1, 1, 2, 3, 4, 5, 5, 5, 6, 7, 2, 2]
print(list(set(a)))
"""
[1, 2, 3, 4, 5, 6, 7]
"""
Il modo più semplice per rimuovere i duplicati da una lista è convertirla in un set (e poi, se vuoi, di nuovo in una lista).
Per mutabilità, set e liste sono simili in Python. Possiamo aggiungere e rimuovere elementi in entrambe, ma sono comunque molto diverse.
Le liste sono ordinate, indicizzate da zero e mutabili. I set sono non ordinati e non indicizzati. Gli elementi in un set devono essere di tipo immutabile, anche se il set stesso è mutabile: provare a recuperare un elemento tramite indice o a modificarlo genererà un errore.
Un'altra differenza chiave è che i set non possono contenere duplicati. È questo che ci ha permesso di rimuovere i duplicati dalla lista.
#13 Underscore standalone
>>> print(_)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
>>> 1 + 2
3
>>> print(_)
3
Il trattino basso (_) è un identificatore valido in Python, quindi è possibile usarlo per riferirsi a un oggetto. Ma ha anche un'altra responsabilità: memorizzare il risultato dell'ultima valutazione.
La documentazione afferma che "l'interprete interattivo rende disponibile il risultato dell'ultima valutazione nella variabile _. (È memorizzata nel modulo builtins, insieme a funzioni come print)."
Poiché non avevamo assegnato alcun oggetto a underscore prima di stamparlo nella prima riga, abbiamo ottenuto un errore. Quando invece abbiamo calcolato 1 + 2, l'interprete interattivo ha memorizzato il risultato nell'identificatore _ .
#14 Underscore per ignorare valori
for _ in range(100):
print("The index doesn't matter")
"""
The index doesn't matter
The index doesn't matter
...
"""
Nel trucco #13 abbiamo visto che l'interprete interattivo rende disponibile nell'identificatore (_) l'ultimo risultato, ma non è il solo caso d'uso.
Possiamo usarlo anche per rappresentare oggetti di cui non ci importa o che non useremo più avanti nel programma. Questo è importante perché usare un identificatore al posto di underscore (_) genererà un errore F841 quando si fa linting: F841 segnala che una variabile locale è stata assegnata ma non usata, una cattiva pratica.
#15 Underscore finale
list_ = [0, 1, 2, 3, 4]
global_ = "Hi there"
Restando sull'uso dell'underscore (_), un altro scopo è evitare conflitti con le keyword di Python.
PEP 8 menziona che un underscore finale dovrebbe essere "usato per convenzione per evitare conflitti con le keyword di Python." Aggiunge anche che "in generale è meglio aggiungere un singolo underscore finale piuttosto che usare abbreviazioni o storpiature. Quindi list_ è meglio di lst."
#16 Underscore iniziale
class Example:
def __init__(self):
self._internal = 2
self.external = 20
Spesso i programmatori Python esperti antepongono un underscore a un identificatore o al nome di un metodo, e a ragione.
L'underscore prefisso ha un significato implicito: questa variabile o metodo è pensata solo per uso interno. In sostanza, è un disclaimer per altri sviluppatori, definito in PEP 8 ma non imposto da Python. Quindi, gli underscore iniziali sono un indicatore debole.
A differenza di Java, Python non ha una distinzione forte tra variabili private e pubbliche. In altre parole, ha senso solo perché la comunità Python ha deciso così. La loro presenza non influisce sul comportamento del programma.
#17 Underscore come separatore visivo
Ecco l'ultimo consiglio sugli underscore. Finora abbiamo visto tre casi d'uso, ma puoi approfondire nel tutorial sul ruolo dell'underscore (_) in Python.
number = 1_500_000
print(number)
"""
15000000
"""
Un altro modo di usare l'underscore è come separatore visivo per raggruppare cifre nei letterali interi, floating-point e complessi – introdotto in Python 3.6.
L'idea è migliorare la leggibilità di numeri lunghi o in cui le parti devono essere chiaramente separate – puoi leggere di più in PEP 515.
Trucchi di stile e sintassi
#18 __name__ == “__main__”
if __name__ == "__main__":
print("Read on to understand what is going on when you do this.")
"""
print("Read on to understand what is going on when you do this.")
"""
È molto probabile che tu abbia visto questa sintassi in diversi programmi Python; Python usa un nome speciale "__main__" e lo assegna all'identificatore __name__ se il file Python eseguito è il programma principale.
Se importiamo il modulo mostrato nello screenshot in un altro modulo (file Python) ed eseguiamo quest'ultimo, l'espressione nel nostro codice risulterà falsa. Questo perché quando importiamo da un altro modulo, l'identificatore __name__ viene impostato al nome del modulo (file Python).
#19 Il metodo ‘setdefault’
import pprint
text = "It's the first of April. It's still cold in the UK. But I'm going to the museum so it should be a wonderful day"
counts = {}
for word in text.split():
counts.setdefault(word, 0)
counts[word] += 1
pprint.pprint(counts)
"""
{'April.': 1,
'But': 1,
"I'm": 1,
"It's": 2,
'UK.': 1,
'a': 1,
'be': 1,
'cold': 1,
'day': 1,
'first': 1,
'going': 1,
'in': 1,
'it': 1,
'museum': 1,
'of': 1,
'should': 1,
'so': 1,
'still': 1,
'the': 3,
'to': 1,
'wonderful': 1}
"""
Potresti voler impostare un valore per varie chiavi in un dizionario. Per esempio, quando tracci i conteggi delle parole in un corpus. Il modo comune è:
- Controllare se la chiave esiste nel dizionario
- Se esiste, incrementare il valore di 1.
- Se non esiste, aggiungerla e impostare il valore a 1.
Ecco come appare in codice:
counts = {}
for word in text.split():
if word in counts:
counts[word] += 1
else:
counts[word] = 1
Un modo più conciso è usare il metodo setdefault() sull'oggetto dizionario.
Il primo argomento passato è la chiave da controllare. Il secondo è il valore da impostare se la chiave non esiste già nel dizionario: se la chiave esiste, il metodo restituisce il valore della chiave e quindi non viene modificato.
Trucchi sulla struttura del programma
#20 Corrispondenza con regex
import re
number = re.compile(r"(0)?(\+44)?\d{10}")
num_1 = number.search("My number is +447999999999")
num_2 = number.search("My number is 07999999999")
print(num_1.group())
print(num_2.group())
"""
'+447999999999'
'07999999999'
"""
Le espressioni regolari permettono di specificare un pattern di testo da cercare; la maggior parte delle persone sa che si può cercare con CTRL + F (Windows), ma se non conosci esattamente cosa cercare, come lo trovi? La risposta è: cerchi i pattern.
Per esempio, i numeri UK seguono un pattern simile: uno zero iniziale più dieci cifre, oppure +44 al posto dello zero e dieci cifre – il secondo caso è il formato internazionale.
Le espressioni regolari fanno risparmiare molto tempo. Se dovessimo codificare regole per catturare i casi in figura invece di usare regex, potremmo arrivare a 10+ righe di codice.
Imparare come funzionano le regex è fondamentale anche se non scrivi codice: la maggior parte degli editor di testo moderni e dei word processor permette di usarle nelle funzioni Trova e sostituisci.
#21 Pipe nelle regex
import re
heros = re.compile(r"Super(man|woman|human)")
h1 = heros.search("This will find Superman")
h2 = heros.search("This will find Superwoman")
h3 = heros.search("This will find Superhuman")
print(h1.group())
print(h2.group())
print(h3.group())
"""
Superman
Superwoman
Superhuman
"""
Le regex hanno un carattere speciale chiamato pipe (|) che ti permette di far corrispondere una tra più espressioni, e può essere usato ovunque. È utilissimo quando hai più pattern simili.
Per esempio, 'Superman', 'Superwoman' e 'Superhuman' hanno lo stesso prefisso. Puoi quindi usare la pipe per mantenere la parte ricorrente del pattern e cambiare le parti che devono differire. Ancora una volta, risparmi tempo prezioso.
Attenzione alla trappola: se tutte le espressioni che vuoi far corrispondere compaiono nello stesso testo, verrà restituita la prima occorrenza che corrisponde – ad esempio, "An example text containing Superwoman, Superman, Superhuman" restituirà Superwoman.
#22 Il parametro ‘sep’ di print()
day = "04"
month = "10"
year = "2022"
print(day, month, year)
print(day, month, year, sep = "")
print(day, month, year, sep = ".")
"""
04 10 2022
04/10/2022
04.10.2022
"""
Il numero di programmatori Python che non conoscono tutte le capacità di print() è sorprendente; se “Hello World” è stato il tuo primo programma, probabilmente print() è stata una delle prime funzioni che hai visto. Usiamo print() per mostrare messaggi formattati a schermo, ma c'è molto di più in print().
Nel codice sopra abbiamo mostrato modi diversi di visualizzare un messaggio formattato. Il parametro sep è un argomento opzionale che ci consente di specificare come separare gli oggetti quando ne includiamo più di uno.
Il default è uno spazio, ma l'abbiamo cambiato nelle nostre stampe: una volta con "" e un'altra con ".".
#23 Funzioni lambda
def square(num:int) -> int:
return num ** 2
print(f"Function call: {square(4)}")
"""
Function call: 16
"""
square_lambda = lambda x: x**2
print(f"Lambda function: {square_lambda(4)}")
"""
Lambda functional: 16
"""
Le funzioni lambda ti portano verso aspetti più intermedi-avanzati di Python – impara Python intermedio con questo corso. A prima vista sembrano complicate, ma sono piuttosto semplici.
Nell'esempio abbiamo usato un solo argomento, ma potremmo usarne più di uno:
square = lambda a, b: a ** b
print(f"Lambda function: {square(4, 2)}")
"""
16
"""
In sostanza, la keyword lambda ci permette di creare piccole funzioni anonime, limitate, in una riga. Si comportano come normali funzioni dichiarate con def, tranne che non hanno un nome.
#24 Il metodo ‘swapcase’
string = "SoMe RaNDoM sTriNg"
print(string.swapcase())
"""
sOmE rAndOm StRInG
"""
Il metodo swapcase() si applica a una stringa per trasformare le maiuscole in minuscole e viceversa in una sola riga di codice. Non ci sono molti casi d'uso, ma è utile saperlo.
#25 Il metodo ‘isalnum’
password = "ABCabc123"
print(password.isalnum())
"""
True
"""
Supponiamo di creare un programma che richiede una password composta da numeri e lettere. Possiamo farlo in una riga chiamando isalnum() sull'istanza di stringa.
Il metodo verifica che tutti i caratteri siano alfabetici (A-Za-z) o numerici (0-9). Uno spazio o un simbolo (!#%$&? ecc.) restituirà False.
#26 Gestione delle eccezioni
def get_ration(x:int, y:int) -> int:
try:
ratio = x/y
except ZeroDivisionError:
y = y + 1
ratio = x/y
return ratio
print(get_ration(x=400, y=0))
"""
400.0
"""
I programmi Python terminano quando incontrano un errore.
A volte, non vogliamo questo comportamento, ad esempio quando un utente finale interagisce col nostro codice. Quanto sarebbe negativo se il programma si chiudesse prematuramente?
Ci sono varie scuole di pensiero su come gestire i casi eccezionali. Molti programmatori Python abbracciano l'idea che è più facile chiedere perdono che ottenere permesso. Preferiscono cioè intercettare un errore sollevato fornendo il contesto per gestire l'eccezione, invece di cercare di prevenire tutti i casi possibili.
Ma questo vale solo se esiste un meccanismo per gestire il problema dopo che si è verificato.
#27 Identificare le differenze tra liste
list_1 = [1, 3, 5, 7, 8]
list_2 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
solution_1 = list(set(list_2) - set(list_1))
solution_2 = list(set(list_1) ^ set(list_2))
solution_3 = list(set(list_1).symmetric_difference(set(list_2)))
print(f"Solution 1: {solution_1}")
print(f"Solution 2: {solution_2}")
print(f"Solution 3: {solution_3}")
"""
Solution 1: [9, 2, 4, 6]
Solution 2: [2, 4, 6, 9]
Solution 3: [2, 4, 6, 9]
"""
Ecco tre modi diversi per confrontare la differenza tra due liste in Python.
Nota: a meno che tu non sappia per certo che list_1 è un sottoinsieme di list_2, la soluzione 1 non è equivalente alle altre due.
#28 Args & kwargs
def some_function(*args, **kwargs):
print(f"Args: {args}")
print(f"Kwargs: {kwargs}")
some_function(1, 2, 3, a=4, b=5, c=6)
"""
Args: (1, 2, 3)
Kwargs: {'a': 4, 'b': 5, 'c': 6}
"""
Usiamo *args e **kwargs come parametri quando non conosciamo a priori il numero di variabili che la funzione deve aspettarsi.
Il parametro *args permette di passare un numero variabile di argomenti posizionali (cioè senza nome associato). Il parametro **kwargs consente di passare un numero arbitrario di argomenti con parola chiave.
In realtà, le parole *args e **kwargs non sono magiche: la vera magia sta negli asterischi (*). Potremmo usare qualsiasi nome dopo gli asterischi, ma args e kwargs sono la pratica comune, adottata tra gli sviluppatori Python.
#29 L'ellipsis
print(...)
"""
Ellipsis
"""
def some_function():
...
# Alternative solution
def another_function():
pass
Ellipsis è un oggetto Python che può essere richiamato fornendo una sequenza di tre puntini (...) o chiamando direttamente l'oggetto (Ellipsis).
Il suo uso più noto è per accedere e fare slicing su array multidimensionali in NumPy, per esempio:
import numpy as np
arr = np.array([[2,3], [1,2], [9,8]])
print(arr[...,0])
"""
[2 1 9]
"""
print(arr[...])
"""
[[2 3]
[1 2]
[9 8]]
"""
Ma un altro uso di Ellipsis è come segnaposto in una funzione non ancora implementata.
Questo significa che puoi usare Ellipsis, ... o pass, e saranno tutti validi.
#30 List comprehension
even_numbers = [x for x in range(10) if x % 2 == 0 and x != 0]
print(even_numbers)
"""
[2, 4, 6, 8]
"""
L'ultimo trucco è la list comprehension, un modo elegante per creare una lista a partire da un'altra sequenza. Permette di applicare logica e filtri sofisticati, come nel codice sopra.
Ci sono altri modi per ottenere lo stesso risultato; ad esempio, potremmo usare una lambda così:
even_numbers = list(filter(lambda x: x % 2 ==0 and x != 0, range(10)))
print(even_numbers)
"""
[0, 2, 4, 6, 8]
"""
Ma molti Pythonisti direbbero che questa soluzione è molto meno leggibile rispetto alla list comprehension.
FAQ
Qual è il trucco Python più utile per i principianti?
Le f-string sono probabilmente le più utili subito. Rendono la formattazione delle stringhe più veloce, più leggibile e meno soggetta a errori rispetto ad approcci più vecchi come .format().
Qual è il modo più rapido per scambiare due variabili in Python?
Usa l'assegnazione simultanea: a, b = b, a. Nessuna variabile temporanea necessaria — Python valuta completamente il lato destro prima di assegnare.
Come unisco due dizionari in una riga?
In Python 3.9+, usa l'operatore |: merged = dict_a | dict_b. Nelle versioni precedenti, usa {**dict_a, **dict_b}.
Qual è la differenza tra *args e **kwargs?
*args raccoglie gli argomenti posizionali extra in una tupla. **kwargs raccoglie gli argomenti con parola chiave extra in un dizionario. La magia sta negli operatori * e **, non nei nomi stessi — potresti chiamarli come vuoi.
Come verifico se una lista è vuota in Python?
Usa l'operatore not: if not my_list:. È più "Pythonic" che controllare len(my_list) == 0.
Qual è la differenza tra una list comprehension e un generator?
Una list comprehension (parentesi quadre) costruisce l'intera lista in memoria in una volta sola. Un generator (parentesi tonde) produce i valori uno alla volta su richiesta, usando molta meno memoria per sequenze grandi.
Quando dovrei usare un operatore ternario?
Usalo per semplici condizionali in una riga, quando entrambi i rami sono brevi e chiari: name = "John" if condition else "Doe". Per qualcosa di più complesso, un normale blocco if/else è più leggibile.
Qual è il modo più semplice per rimuovere i duplicati da una lista?
Racchiudila in set() e riconverti: list(set(my_list)). Nota che i set non sono ordinati, quindi l'ordine originale non sarà preservato.