ProgrammatieBackend ontwikkelaar

Beschrijf het mechanisme van lijstbegrip (list comprehensions) in Python. Wat is het verschil tussen list comprehension en de functie map() en for-lussen, wat zijn de voor- en nadelen van elke benadering, en welke fouten kunnen zich voordoen bij onjuist gebruik?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Lijstbegrippen (list comprehensions) zijn een beknopte manier om lijsten te maken op basis van bestaande iterabele objecten met behulp van een korte syntaxis:

squares = [x**2 for x in range(10)]

Deze notatie is equivalent aan:

squares = [] for x in range(10): squares.append(x**2)

Lijstbegrippen hebben verschillende voordelen:

  • Bondigheid en leesbaarheid (vooral voor eenvoudige transformaties);
  • Mogelijkheid om voorwaarden (filter) op te nemen: evens = [x for x in range(10) if x % 2 == 0];
  • De expressies geven meteen een lijst terug, waarvan het resultaat later kan worden gebruikt.

Een analogie met map():

def f(x): return x**2 squares = list(map(f, range(10)))

map is sneller bij grote gegevens als een functie die al op C bestaat wordt gebruikt, en is geschikt voor het toepassen van één functie op alle elementen. Lijstbegrip is voor alle expressies, en niet alleen voor kant-en-klare functies. Een for-lus is flexibeler, maar omvangrijker.


Vraag met een valstrik.

Waarom is de variabele x na het uitvoeren van een lijstbegrip zoals [x for x in range(10)] toegankelijk buiten de expressie in Python2, maar niet in Python3?

Antwoord: In Python2 behoudt de loopvariabele (x) zijn waarde na het uitvoeren van de lijstbegrip. In Python3 wordt hij "geïsoleerd" en is hij buiten de lijst niet toegankelijk, wat ongewenste bijeffecten voorkomt.

Voorbeeld:

# Python 2.x: [x for x in range(3)] print(x) # x == 2 # Python 3.x: [x for x in range(3)] print(x) # NameError: name 'x' is not defined

Voorbeelden van echte fouten door onwetendheid over de nuances van het onderwerp.


Verhaal 1

Een ontwikkelaar in een groot project wilde filteren en een nieuwe lijst maken via een lijstbegrip:

my_list = [item.transform() for item in data if item.is_valid()]

Maar de operatie item.transform() gaf een foutmelding als item.is_valid() False teruggeef. De controlefunctie was echter geschreven met een potentieel side effect, en uiteindelijk brak het lijstbegrip onopvallend delen van de code met bijeffecten.


Verhaal 2

Bij het migreren van Python2 naar Python3 was de ontwikkelaar ervan overtuigd dat de loopvariabele toegankelijk zou blijven:

[x for x in range(5)] print(x) # Verwacht 4, maar kreeg NameError.

Dit veroorzaakte een bug in de cyclische logica, waar de variabele buiten de comprehension beschikbaar moest blijven.


Verhaal 3

Gebruik van geneste lijstbegrippen zonder expliciete aanduiding van niveaus:

def flatten(matrix): return [cell for row in matrix for cell in row]

Beginners maken vaak fouten door de verkeerde volgorde van doorloop te gebruiken (bijvoorbeeld [cell for cell in row for row in matrix] of onnodige nesting), wat leidt tot een onjuiste uitkomst — een eendimensionale lijst in plaats van een tweedimensionale of omgekeerd.