Tracks
/
Python
Python
/
Lehrplan
/
Entpacken und Mehrfachzuweisung
En

Entpacken und Mehrfachzuweisung in Python

3 Übungen

Über Entpacken und Mehrfachzuweisung

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).

Caution

*<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.

Mehrfachzuweisung

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.

Entpacken

Note

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"

Tiefes Entpacken

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)

Eine list/tuple mit * entpacken

Beim 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"]

Ein Wörterbuch entpacken

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

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.

Eine list/tuple mit * packen

Eine 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.

Ein Wörterbuch mit ** packen

Ein 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}

Verwendung von * und ** mit Funktionen

Packen mit Funktionsparametern

Wenn 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.

Caution

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'

In Funktionsaufrufe entpacken

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)]
Über GitHub bearbeiten Der Link öffnet sich in einem neuen Fenster oder Tab

Lerne Entpacken und Mehrfachzuweisung

Das Üben ist gesperrt

Schalte 3 weitere Übungen frei, um Entpacken und Mehrfachzuweisung zu üben