Beim Entpacken werden die Elemente einer Sammlung wie einer list, eines tuple oder eines dict mithilfe von Iteration herausgezogen.
Die entpackten Werte kannst du dann innerhalb derselben Anweisung Variablen zuweisen.
Ein sehr häufiges Beispiel dafür ist for item in list: Dabei nimmt item im Laufe der Iteration nacheinander den Wert jedes Elements der list an.
Mehrfachzuweisung ist die Möglichkeit, innerhalb einer Anweisung mehreren Variablen entpackte Werte zuzuweisen.
So wird dein Code kürzer und lesbarer. Dazu trennst du die zuzuweisenden Variablen mit einem Komma, zum Beispiel first, second, third = (1,2,3) oder for index, item in enumerate(iterable).
Die speziellen Operatoren * und ** werden oft beim Entpacken verwendet.
Mit * kannst du mehrere lists/tuples zu einer einzigen list/tuple zusammenfassen, indem du jede davon in eine neue gemeinsame list/tuple entpackst.
Mit ** kannst du mehrere Wörterbücher zu einem einzigen Wörterbuch zusammenfassen, indem du jedes davon in ein neues gemeinsames dict entpackst.
Wenn der Operator * ohne eine Sammlung verwendet wird, packt er eine Anzahl von Werten in eine list.
Das wird bei der Mehrfachzuweisung oft genutzt, um alle „übrig gebliebenen“ Elemente, die keine eigene Zuweisung haben, in einer einzigen Variablen zusammenzufassen.
In Python nutzt man dieses Pack- und Entpackverhalten auch häufig, wenn man Funktionen verwendet oder definiert, die eine beliebige Anzahl von Positions- oder Schlüsselwortargumenten entgegennehmen.
Du siehst dann oft diese „speziellen“ Parameter in der Form def some_function(*args, **kwargs) und die „speziellen“ Argumente als some_function(*some_tuple, **some_dict).
*<variable_name> und **<variable_name> darfst du nicht mit * und ** verwechseln. * und ** stehen für Multiplikation bzw. Potenzierung, während *<variable_name> und **<variable_name> als Pack- und Entpackoperatoren verwendet werden.
Bei der Mehrfachzuweisung muss die Anzahl der Variablen links vom Zuweisungsoperator (=) mit der Anzahl der Werte auf der rechten Seite übereinstimmen.
Trenne die Werte mit einem Komma ,:
>>> a, b = 1, 2
>>> a
1
Bekommt die Mehrfachzuweisung eine falsche Anzahl von Variablen für die angegebenen Werte, wird ein ValueError ausgelöst:
>>> x, y, z = 1, 2
ValueError: too many values to unpack (expected 3, got 2)
Die Mehrfachzuweisung ist nicht auf einen Datentyp beschränkt:
>>> x, y, z = 1, "Hello", True
>>> x
1
>>> y
'Hello'
>>> z
True
Mit der Mehrfachzuweisung kannst du Elemente in lists vertauschen.
Das ist in Sortieralgorithmen recht üblich.
Zum Beispiel:
>>> numbers = [1, 2]
>>> numbers[0], numbers[1] = numbers[1], numbers[0]
>>> numbers
[2, 1]
Da tuples unveränderlich sind, kannst du Elemente in einem tuple nicht vertauschen.
Die folgenden Beispiele verwenden lists, aber dieselben Konzepte gelten auch für tuples.
In Python kannst du die Elemente einer list/tuple/dict entpacken und auf einzelne Variablen verteilen.
Da Werte in lists/tuples in einer bestimmten Reihenfolge stehen, werden sie in derselben Reihenfolge auf die Variablen verteilt:
>>> fruits = ["apple", "banana", "cherry"]
>>> x, y, z = fruits
>>> x
"apple"
Wenn du manche Werte nicht brauchst, kannst du sie mit _ markieren:
>>> fruits = ["apple", "banana", "cherry"]
>>> _, _, z = fruits
>>> z
"cherry"
Das Entpacken und Zuweisen von Werten aus einer list/tuple innerhalb einer list oder tuple (auch als verschachtelte Listen/Tupel bekannt) funktioniert genauso wie ein flaches Entpacken, braucht aber oft zusätzliche Angaben, um Kontext oder Position des Werts klarzumachen:
>>> fruits_vegetables = [["apple", "banana"], ["carrot", "potato"]]
>>> [[a, b], [c, d]] = fruits_vegetables
>>> a
"apple"
>>> d
"potato"
Du kannst auch nur einen Teil einer verschachtelten list/tuple tief entpacken:
>>> fruits_vegetables = [["apple", "banana"], ["carrot", "potato"]]
>>> [a, [c, d]] = fruits_vegetables
>>> a
["apple", "banana"]
>>> c
"carrot"
Wenn beim Entpacken die Variablen falsch angeordnet sind und/oder die Anzahl der Werte nicht stimmt, bekommst du einen ValueError:
>>> fruits_vegetables = [["apple", "banana"], ["carrot", "potato"]]
>>> [[a, b], [d]] = fruits_vegetables
ValueError: too many values to unpack (expected 1)
* entpackenBeim Entpacken einer list/tuple kannst du den Operator * verwenden, um „übrig gebliebene“ Werte aufzufangen.
Das ist klarer als ein Slicing der list/tuple (was in manchen Situationen weniger lesbar ist).
Zum Beispiel können wir das erste Element herausnehmen und die restlichen Werte in eine neue list ohne das erste Element packen:
>>> fruits = ["apple", "banana", "cherry", "orange", "kiwi", "melon", "mango"]
>>> x, *last = fruits
>>> x
"apple"
>>> last
["banana", "cherry", "orange", "kiwi", "melon", "mango"]
Wir können auch die Werte am Anfang und am Ende der list herausnehmen und dabei alle Werte dazwischen gruppieren:
>>> fruits = ["apple", "banana", "cherry", "orange", "kiwi", "melon", "mango"]
>>> x, *middle, y, z = fruits
>>> y
"melon"
>>> middle
["banana", "cherry", "orange", "kiwi"]
* lässt sich auch beim tiefen Entpacken verwenden:
>>> fruits_vegetables = [["apple", "banana", "melon"], ["carrot", "potato", "tomato"]]
>>> [[a, *rest], b] = fruits_vegetables
>>> a
"apple"
>>> rest
["banana", "melon"]
Das Entpacken eines Wörterbuchs unterscheidet sich ein wenig vom Entpacken einer list/tuple.
Bei der Iteration über Wörterbücher werden standardmäßig die Schlüssel verwendet.
Wenn du ein dict entpackst, kannst du also nur die Schlüssel entpacken, nicht die Werte:
>>> fruits_inventory = {"apple": 6, "banana": 2, "cherry": 3}
>>> x, y, z = fruits_inventory
>>> x
"apple"
Wenn du die Werte entpacken möchtest, kannst du die Methode <dict>.values() verwenden:
>>> fruits_inventory = {"apple": 6, "banana": 2, "cherry": 3}
>>> x, y, z = fruits_inventory.values()
>>> x
6
Wenn du sowohl Schlüssel als auch Werte brauchst, verwende die Methode <dict>.items().
<dict>.items() erzeugt eine iterierbare Ansicht, die Schlüssel-Wert-Paare enthält.
Diese Paare kannst du in ein tuple entpacken:
>>> fruits_inventory = {"apple": 6, "banana": 2, "cherry": 3}
>>> x, y, z = fruits_inventory.items()
>>> x
("apple", 6)
Packen ist die Möglichkeit, mehrere Werte zu einer einzigen list zusammenzufassen, die einer Variablen zugewiesen wird.
Das ist praktisch, wenn du Werte entpacken, ändern und die Ergebnisse anschließend wieder in eine Variable packen möchtest.
Außerdem kannst du damit zwei oder mehr lists/tuples/dicts zusammenführen.
* packenEine list/tuple kannst du mit dem Operator * packen.
Dabei werden alle Werte in eine list/tuple gepackt.
>>> fruits = ("apple", "banana", "cherry")
>>> more_fruits = ["orange", "kiwi", "melon", "mango"]
# fruits and more_fruits are unpacked and then their elements are packed into combined_fruits
>>> combined_fruits = *fruits, *more_fruits
# If there is no * on to the left of the "=" the result is a tuple
>>> combined_fruits
("apple", "banana", "cherry", "orange", "kiwi", "melon", "mango")
# If the * operator is used on the left side of "=" the result is a list.
# Note the trailing comma.
>>> *combined_fruits_too, = *fruits, *more_fruits
>>> combined_fruits_too
['apple', 'banana', 'cherry', 'orange', 'kiwi', 'melon', 'mango']
# A list literal can be used instead, but might not be as readable.
>>> [*combined_fruits_too] = *fruits, *more_fruits
>>> combined_fruits_too
['apple', 'banana', 'cherry', 'orange', 'kiwi', 'melon', 'mango']
Mehr Details zur Verwendung von * und ** findest du in PEP 3132 und PEP 448.
** packenEin Wörterbuch packst du mit dem Operator **.
Dabei werden alle Schlüssel-Wert-Paare aus einem Wörterbuch in ein anderes Wörterbuch gepackt, oder zwei Wörterbücher werden zusammengeführt.
>>> fruits_inventory = {"apple": 6, "banana": 2, "cherry": 3}
>>> more_fruits_inventory = {"orange": 4, "kiwi": 1, "melon": 2, "mango": 3}
# fruits_inventory and more_fruits_inventory are unpacked into key-values pairs and combined.
>>> combined_fruits_inventory = {**fruits_inventory, **more_fruits_inventory}
# then the pairs are packed into combined_fruits_inventory
>>> combined_fruits_inventory
{"apple": 6, "banana": 2, "cherry": 3, "orange": 4, "kiwi": 1, "melon": 2, "mango": 3}
* und ** mit FunktionenWenn du eine Funktion erstellst, die eine beliebige Anzahl von Argumenten annimmt, kannst du in der Funktionsdefinition *args oder **kwargs verwenden.
Mit *args packst du eine beliebige Anzahl von Positionsargumenten (ohne Schlüsselwort), mit **kwargs eine beliebige Anzahl von Schlüsselwortargumenten.
Verwendung von *args:
# This function is defined to take any number of positional arguments
>>> def my_function(*args):
... print(args)
# Arguments given to the function are packed into a tuple
>>> my_function(1, 2, 3)
(1, 2, 3)
>>> my_function("Hello")
("Hello")
>>> my_function(1, 2, 3, "Hello", "Mars")
(1, 2, 3, "Hello", "Mars")
Verwendung von **kwargs:
# This function is defined to take any number of keyword arguments
>>> def my_function(**kwargs):
... print(kwargs)
# Arguments given to the function are packed into a dictionary
>>> my_function(a=1, b=2, c=3)
{"a": 1, "b": 2, "c": 3}
*args und **kwargs kannst du auch miteinander kombinieren:
>>> def my_function(*args, **kwargs):
... print(sum(args))
... for key, value in kwargs.items():
... print(str(key) + " = " + str(value))
>>> my_function(1, 2, 3, a=1, b=2, c=3)
6
a = 1
b = 2
c = 3
Du kannst auch Parameter vor *args schreiben, um bestimmte Positionsargumente zuzulassen.
Einzelne Schlüsselwortargumente müssen dann vor **kwargs stehen.
So müssen Argumente aufgebaut sein:
def my_function(<positional_args>, *args, <key-word_args>, **kwargs)
Wenn du diese Reihenfolge nicht einhältst, bekommst du einen Fehler.
>>> def my_function(a, b, *args):
... print(a)
... print(b)
... print(args)
>>> my_function(1, 2, 3, 4, 5)
1
2
(3, 4, 5)
Schreibst du die Argumente in der falschen Reihenfolge, führt das zu einem Fehler:
>>> def my_function(*args, a, b):
... print(args)
>>>my_function(1, 2, 3, 4, 5)
Traceback (most recent call last):
File "c:\something.py", line 3, in <module>
my_function(1, 2, 3, 4, 5)
TypeError: my_function() missing 2 required keyword-only arguments: 'a' and 'b'
Mit * kannst du eine list/tuple von Argumenten in einen Funktionsaufruf entpacken.
Das ist sehr nützlich für Funktionen, die kein iterable akzeptieren:
>>> def my_function(a, b, c):
... print(c)
... print(b)
... print(a)
numbers = [1, 2, 3]
>>> my_function(*numbers)
3
2
1
Ein weiterer häufiger Anwendungsfall ist das Entpacken mit * zusammen mit der eingebauten Funktion zip().
Die Funktion zip() nimmt mehrere iterables und gibt eine list aus tuples zurück, in der die Werte aus jedem iterable gruppiert sind:
>>> values = (['x', 'y', 'z'], [1, 2, 3], [True, False, True])
>>> a, *rest = zip(*values)
>>> rest
[('y', 2, False), ('z', 3, True)]