Geschiedenis van de vraag:
De operators * en ** voor uitpakken zijn al lang in Python aanwezig, maar hun toepassing is met elke versie uitgebreid (bijvoorbeeld, ondersteuning voor het combineren van meerdere verzamelingen met * en ** is toegevoegd in Python 3.5). Deze operators maken het werken met verzamelingen flexibeler, vooral bij het doorgeven van argumenten en het verzamelen ervan in functies.
Probleem:
Zonder uitpakken, bij het werken met dynamische reeksen en het doorgeven van parameters met een variabel aantal argumenten, is er behoefte aan handmatig geschreven lussen en controles van de dimensie van verzamelingen. Fouten kunnen gemakkelijk ontstaan bij onjuiste gebruik of als men het doel van * en ** niet onderscheidt.
Oplossing:
De operator * is bedoeld voor het uitpakken van reeksen (lijst, tuple, set), terwijl de operator ** is voor het uitpakken van woordenboeken bij functie-aanroepen of het combineren van meerdere woordenboeken. Ze stellen ons in staat om elegant argumenten door te geven, verzamelingen samen te voegen en willekeurige structuren eenvoudig om te zetten in functieparameters.
Codevoorbeeld:
def foo(a, b, c): print(a, b, c) args = (1, 2, 3) foo(*args) # 1 2 3 params = {'a': 10, 'b': 20, 'c': 30} foo(**params) # 10 20 30 list1 = [1, 2] list2 = [3, 4] combined = [*list1, *list2] print(combined) # [1, 2, 3, 4]
Kernfeatures:
*sequence geeft elementen door als afzonderlijke positionele argumenten, **dict als benoemde argumenten.[*a, *b] en {**d1, **d2}.Kun je * en ** gebruiken voor gemengde verzamelingen?
Bij een functie-aanroep werkt * alleen met positionele argumenten, terwijl ** alleen met benoemde argumenten werkt. Als je een niet-uitgepakt dict als * doorgeeft of een reeks als **, zal er een fout optreden.
def foo(a, b): print(a, b) foo(*{'a': 1, 'b': 2}) # Print: a b (sleutels van het woordenboek, niet de waarden!)
**Wat gebeurt er als de sleutelnamen overlappen bij het combineren van dicts met {**d1, d2}?
Als gevolg daarvan is de waarde van de laatste woordenboek met die sleutel.
d1 = {'x': 1, 'y': 2} d2 = {'y': 33, 'z': 44} merged = {**d1, **d2} print(merged) # {'x': 1, 'y': 33, 'z': 44}
Kun je * en ** gebruiken binnen list- of dict-expressies?
Ja, dit is toegestaan sinds Python 3.5, bijvoorbeeld:
lst = [1, 2, *range(3, 6)] # [1, 2, 3, 4, 5] dct = {**{'a': 1}, 'b': 2, **{'c': 3}}
Een ontwikkelaar neemt een dict als invoer en parseert deze met * in plaats van **. Dit leidt tot onverwacht gedrag: de functie krijgt niet de waarden maar de sleutels.
Voordelen:
De code faalt niet meteen, lijkt “werkend”.
Nadelen:
Verborgen fouten en inconsistentie met de verwachte logica.
Juiste overdracht van parameters via **kwargs, nette samenvoeging van woordenboeken, gebruik van * bij dynamische samenvoeging van reeksen.
Voordelen:
Maximale flexibiliteit, beknoptheid van de code, eenvoud in refactoring.
Nadelen:
Bij een groot aantal parameters en verzamelingen is het belangrijk om goed op de namen en volgorde te letten, anders kunnen er fouten ontstaan.