ProgrammazioneData Engineer

Descrivi il funzionamento della funzione map() in Python. In cosa si differenzia dalle espressioni generatore e dalle espressioni di lista, in quali casi map è preferibile e quando no?

Supera i colloqui con l'assistente IA Hintsage

Risposta.

Storia della domanda

La funzione map() proviene dalla programmazione funzionale (fin dagli albori di Lisp), ed è progettata per applicare una funzione a ogni elemento di una sequenza restituendo un nuovo oggetto iterable con i risultati. In Python è stata introdotta molto prima dell'arrivo delle espressioni generatore e delle espressioni di lista, ma continua ad essere ampiamente utilizzata, specialmente in grandi pipeline di elaborazione dati.

Problema

Se è necessario modificare ogni elemento di una collezione secondo una certa regola, le soluzioni basate sui cicli for tendono a diventare ingombranti e meno leggibili. Le espressioni di lista e map() consentono di esprimere l'intento in modo compatto. È importante comprendere le differenze tra questi approcci per scegliere lo strumento giusto.

Soluzione

  • map(func, iterable) crea un iteratore pigro, in cui gli elementi della sequenza originale sono trasformati dalla funzione func
  • In Python 3, l'oggetto map non calcola gli elementi immediatamente, ma lavora in modo pigro
def square(x): return x * x squares = map(square, [1, 2, 3]) print(list(squares)) # [1, 4, 9]

L'espressione di lista [square(x) for x in [1, 2, 3]] fa lo stesso, ma restituisce immediatamente una lista, mentre l'espressione generatore (square(x) for x in [1, 2, 3]) è un generatore pigro.

Caratteristiche chiave:

  • map() restituisce sempre un iteratore pigro
  • Utile per lavorare con più collezioni (con più argomenti) — map(f, a, b)
  • Non supporta condizioni di filtraggio con una sintassi diretta (a differenza delle espressioni di lista)

Domande trabocchetto.

Restituisce map() una lista in Python 3?

No, a partire da Python 3, map() non restituisce una lista, ma un iteratore pigro. Per ottenere una lista, è necessario racchiudere manualmente il risultato in list().

res = map(str.upper, ['a', 'b']) print(res) # <map object ...> print(list(res)) # ['A', 'B']

È possibile utilizzare map() per aggiungere una condizione di filtraggio all'interno della funzione?

No, map() non filtra gli elementi, ma li trasforma. Per il filtraggio usa filter() o un'espressione di lista:

result = map(str.upper, ['a', 'b', None]) # Se arriva None, map solleverà un errore chiamando str.upper(None) # filter aiuterà a rimuovere None prima di map

È possibile utilizzare map() per scorrere contemporaneamente due sequenze?

Sì, map() può accettare un numero qualsiasi di sequenze e la funzione di trasformazione deve accettare lo stesso numero di argomenti:

x = [1, 2, 3] y = [10, 20, 30] result = map(lambda a, b: a + b, x, y) print(list(result)) # [11, 22, 33]

Errori comuni e anti-pattern

  • Aspettarsi che map() restituisca una lista in Python 3
  • Tentare di filtrare all'interno di map() — map si occupa solo della trasformazione
  • Passare sequenze di lunghezza diversa — le linee vengono troncate alla lunghezza minima

Esempio della vita reale

Caso negativo

Il programmatore si aspetta di ottenere una lista immediatamente:

mapped = map(abs, [-1, -2, -3]) print(mapped[1]) # TypeError: 'map' object is not subscriptable

Vantaggi:

  • Risparmia memoria

Svantaggi:

  • Errore nel tentativo di accedere per indice
  • Richiede conversione in list()

Caso positivo

Utilizzo di un'espressione generatore per il filtraggio e map() per la trasformazione:

nums = range(-5, 6) positives = (x for x in nums if x > 0) sq = map(lambda n: n * n, positives) print(list(sq)) # [1, 4, 9, 16, 25, 36]

Vantaggi:

  • Facile da combinare con i filtri
  • Minimo consumo di memoria

Svantaggi:

  • Minore leggibilità per i principianti
  • Nessun supporto sintattico per la condizione