Kurs
Die meisten von uns nutzen Sternchen als Operatoren für Multiplikation und Potenzen. In Python haben sie jedoch als Präfix-Operatoren noch eine ganze Reihe weiterer Anwendungen. Nach diesem Artikel kennst du das komplette Einsatzspektrum von Sternchen.
Sternchen decken in Python viele spezielle Anwendungsfälle ab. Üblicherweise kennen wir sie als Multiplikations- und Potenzoperator. Sie können aber je nach Situation auch andere Aufgaben übernehmen, etwa Unpacking oder das Übergeben von Argumenten. Schauen wir uns zuerst die allgemeine Verwendung von Sternchen an.
Allgemeine Verwendung von * und **
* dient als Multiplikationsoperator, ** als Potenzoperator.
## declaring variables
a, b = 2,3
## multiplication
print("Multiplication of 2 and 3 is {}".format(a * b))
## as power operator
print("2 power 3 is {}".format(a ** b))
Multiplication of 2 and 3 is 6
2 power 3 is 8
Das sind die grundsätzlichen und am häufigsten genutzten Sternchen. Es gibt jedoch Einsatzszenarien für Sternchen, die weniger bekannt sind. Schauen wir uns die versteckten Möglichkeiten von Sternchen an.
1. Unpacking mit *
Mit * kannst du Elemente aus einer Liste/einem Tupel/einer Menge entpacken. Wir verwenden Unpacking später im Code, um weitere Features der Sternchen zu zeigen. Unpacking ist die Grundidee hinter dem Einsatz von Sternchen als Präfixoperatoren.
Angenommen, wir wollen das erste Element einer Liste/eines Tupels/einer Menge a zuweisen und die restlichen Elemente b. Üblicherweise würden wir das per Slicing lösen.
## general approach
nums = [i for i in range(1, 6)]
a = nums[0]
b = nums[1:]
print(a, b)
print("--------------------------")
## hard approach
squares = [i ** 2 for i in range(1, 6)]
a = squares[0]
b = []
for i in range(1, len(squares)):
b.append(squares[i])
print(a, b)
1 [2, 3, 4, 5]
--------------------------
1 [4, 9, 16, 25]
Jetzt nutzen wir den *-Operator, um das Ganze in einer einzigen Codezeile umzusetzen.
nums = [i for i in range(1, 6)]
## a wird 1, b wird eine Liste mit den übrigen Elementen
a, *b = nums
print(a, b)
1 [2, 3, 4, 5]
Hier ist a der Wert aus der Liste und b eine Liste. Unpacking funktioniert bei Tupeln und Mengen genauso wie bei Listen. Beispiele:
## using tuple
## here first element will assign to a and last element to c
a, *b, c = (1, 2, 3, 4, 5)
print(a, b, c)
print("--------------------------")
## using sets
a, *b, c = {1, 4, 9, 16, 25}
print(a, b, c)
1 [2, 3, 4] 5
--------------------------
1 [4, 9, 16] 25
1.1. Verschiedene Iterables kombinieren
Per Unpacking lassen sich unterschiedliche Iterables zu Listen/Mengen/Tupeln zusammenführen. Normalerweise müssten wir sie konvertieren und dann zusammenführen. Mit * ist das nicht nötig. Ein Beispiel:
## combining a tuple, list, set
nums = [1, 2, 3]
nums2 = (4, 5, 6)
nums3 = {7, 8, 9}
## we convert the combined elements into any iterable we want
## here i am converting into a list
_list = [*nums, *nums2, *nums3]
_tuple = (*nums, *nums2, *nums3)
_set = {*nums, *nums2, *nums3}
print(type(_list))
print(_list)
print("------------------------")
print(type(_tuple))
print(_tuple)
print("------------------------")
print(type(_set))
print(_set)
<class 'list'>
[1, 2, 3, 4, 5, 6, 8, 9, 7]
------------------------
<class 'tuple'>
(1, 2, 3, 4, 5, 6, 8, 9, 7)
------------------------
<class 'set'>
{1, 2, 3, 4, 5, 6, 7, 8, 9}
1.2. Verschachteltes Unpacking
Verschachteltes Unpacking bedeutet, Elemente aus der ersten Ebene der bereits entpackten Werte weiter aufzuschlüsseln. Das Beispiel macht es klar:
languages = ["Python", "HTML", "CSS", "JS"]
## unpacking
[[first_letter, *remaining], *other] = languages
print(first_letter, remaining, other)
P ['y', 't', 'h', 'o', 'n'] ['HTML', 'CSS', 'JS']
2. Unpacking mit **
Wie wir gesehen haben, dient ** dazu, Elemente aus einem Dictionary zu entpacken. Wir müssen die Keys kennen, um beim Unpacking an die Werte zu kommen. Beispiel:
## sample dictionary
person = {"name":"John", "age":19, "year_of_passing":"2021"}
string = "Name:-{name} Year Of Graduation:-{year_of_passing} Age:-{age}".format(**person)
print(string)
Name:-John Year Of Graduation:-2021 Age:-19
In der Praxis wird ** zum Entpacken aus Dictionaries weniger häufig genutzt.
3. Sternchen in Funktionen
In Funktionen können wir mit Sternchen Argumente übergeben und sammeln – das spart Codezeilen.
3.1. Unpacking in Funktionen
Mit dem *-Operator rufen wir eine Funktion auf, indem wir ein Iterable entpacken. Angenommen, wir haben eine Liste und wollen alle Elemente einzeln an print() übergeben. Deine erste Idee wäre vermutlich eine Schleife. Mit * geht es deutlich einfacher.
Übergebe das Iterable einfach als *iterable_name. Dadurch wird es entpackt und alle Elemente werden separat übergeben.
nums = [i for i in range(1, 6)]
## passsing list using the *
print(*nums)
1 2 3 4 5
nums = (i for i in range(1, 6))
## passsing tuple using the *
print(*nums, sep = ", ")
1, 2, 3, 4, 5
3.2. Elemente packen
Packing bedeutet, mehrere Elemente auf einmal zu erfassen. Das nutzen wir beim Funktionsaufruf.
def average(*nums):
return sum(nums) / len(nums)
Jetzt können wir eine beliebige Anzahl an Ganzzahlen übergeben, um den Durchschnitt zu berechnen. Die Funktion average sammelt alle Argumente als Liste.
## calling the average with some numbers
print(average(1, 2, 3, 4, 5))
3.0
Wir haben gesehen, wie man mit * mehrere Elemente in einer Liste erfasst. Als Nächstes schauen wir, wie sich mit ** beliebig viele Key-Value-Paare erfassen lassen.
def _object(name, **properties):
print(name, properties)
_object("Car", color="Red", cost=999999, company="Ferrari")
Car {'ceo': 'Louis', 'color': 'Red', 'cost': 999999, 'company': 'Ferrari'}
4. Keyword-only-Argumente mit Positionsargumenten
Argumente mit Namen heißen Keyword-Argumente. Alle anderen sind Positionsargumente. Zuerst der Unterschied zwischen Keyword- und Positionsargumenten. Beispiel:
## name is a positional argument
## color and cost are keyword arguments
def sample(car, color = None, cost = None):
print("Car:-{} Color:-{}, Cost:-{}".format(car, color, cost))
Keyword-Argumente können wir beim Funktionsaufruf über den Parameternamen setzen. Wenn wir für ein Keyword-Argument nichts angeben, greift der Standardwert aus der Funktionsdefinition.
Keyword-Argumente lassen sich über die Schlüsselwörter oder die Position angeben.
sample("Ferrari", "Red", 999999)
Car:-Ferrari Color:-Red, Cost:-999999
sample("Ferrari", cost = 999999, color = "Red")
Car:-Ferrari Color:-Red, Cost:-999999
Die Reihenfolge der Keyword-Argumente ist egal, solange wir sie mit ihren Namen angeben.
sample("Ferrari", color = "Green")
Car:-Ferrari Color:-Green, Cost:-None
Jetzt kennst du den Unterschied zwischen Positions- und Keyword-Argumenten. Weiter zum Kernthema.
Keyword-only-Argumente können ausschließlich über Keywords gesetzt werden. Positionsangaben sind – wie oben gezeigt – nicht möglich. Wir deklarieren Keyword-Argumente nach dem *-Argument, um sie als keyword-only zu erzwingen.
def keyword_only(*items, _list, default = False):
print(items)
print(_list)
print(default)
Beim Aufruf müssen wir die _list- und default-Keywords verwenden, da sie nach *items stehen. Ohne Keywords erhalten wir einen Fehler. Beide Fälle:
nums = [i ** 2 for i in range(1, 6)]
## calling the function
keyword_only(1, 2, 3, 4, 5, _list = nums, default = True)
(1, 2, 3, 4, 5)
[1, 4, 9, 16, 25]
True
Was passiert, wenn wir keyword_only nur mit Positionsargumenten aufrufen?
nums = [i ** 2 for i in range(1, 6)]
## calling the function will raise an error
keyword_only(1, 2, 3, 4, 5, nums, False)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-85-bf737d8a8bfc> in <module>()
1 nums = [i ** 2 for i in range(1, 6)]
----> 2 keyword_only(1, 2, 3, 4, 5, nums, False)
TypeError: keyword_only() missing 1 required keyword-only argument: '_list'
Die Fehlermeldung sagt, dass ein erforderliches Keyword-only-Argument fehlt. Daher müssen wir bei Keyword-only-Argumenten die Keywords verwenden. Keyword-only-Argumente stehen in Funktionen immer hinter dem *-Argument.
5. Keyword-only-Argumente ohne Positionsargumente
Wenn wir ausschließlich Keyword-only-Argumente ohne Positionsargumente akzeptieren möchten, erlaubt Python dafür ein einzelnes * in der Parameterliste. Beispiel:
def _sample(*, name):
print(name)
Diese Funktion akzeptiert nur Keyword-only-Argumente. Das Argument muss mit dem Keyword übergeben werden, sonst gibt es einen Fehler. Das * in der Funktionssignatur stellt sicher, dass Argumente nur über Keywords übergeben werden dürfen. Alle Parameter, die in der Definition auf * folgen, müssen beim Aufruf per Keyword gesetzt werden.
## calling the function using keyword 'name'
_sample(name = "Datacamp")
Datacamp
## calling the function without using keyword 'name'
## we will get a TypeError
_sample("Datacamp")
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-12-fe0d3718b56c> in <module>()
1 ## calling the function without using keyword 'name'
2 ## we will get a TypeError
----> 3 samp("Datacamp")
TypeError: samp() takes 0 positional arguments but 1 was given
Es ist eindeutig: _sample() akzeptiert nur Keyword-only*-Argumente.
Fazit
Mit jeder neuen Version erhält Python praktische Features. Sternchen sind dabei besonders nützlich und sparen Code. Mehrere Positionsargumente lassen sich ohne * nicht einfangen, und für Keyword-only-Argumente brauchen wir * ebenfalls. Viele Operationen mit Sternchen wären sonst nur mit mehreren Codezeilen möglich. Übe die gezeigten Techniken, um sie wirklich zu verinnerlichen. Danke fürs Lesen!
Wenn du mehr über Python lernen willst, schau dir den DataCamp-Kurs Python Data Science Toolbox (Part 1) an.
Viel Spaß beim Coden :)


