Python unterstützt die folgenden grundlegenden Vergleichsoperatoren:
| Operator | Operation | Beschreibung |
|---|---|---|
> |
„größer als" |
a > b ist True, wenn a strikt größer als b ist |
< |
„kleiner als" |
a < b ist True, wenn a strikt kleiner als b ist |
== |
„gleich" |
a == b ist True, wenn a strikt gleich b ist |
>= |
„größer oder gleich" |
a >= b ist True, wenn a > b ODER a == b gilt |
<= |
„kleiner oder gleich" |
a <= b ist True, wenn a < b oder a == b gilt |
!= |
„ungleich" |
a != b ist True, wenn a == b False ist |
is |
„Identität" |
a is b ist True, wenn und nur wenn a und b dasselbe Objekt sind |
is not |
„negierte Identität" |
a is not b ist True, wenn a und b nicht dasselbe Objekt sind |
in |
„Mitgliedschaftstest" |
a in b ist True, wenn a Mitglied, Teilmenge oder Element von b ist |
not in |
„negierter Mitgliedschaftstest" |
a not in b ist True, wenn a kein Mitglied, keine Teilmenge und kein Element von b ist |
Sie alle haben dieselbe Priorität (die höher ist als die von booleschen Operationen, aber niedriger als die von arithmetischen oder bitweisen Operationen).
Objekte unterschiedlichen Typs (außer numerischen Typen) sind standardmäßig nie gleich.
Auch nicht identische Instanzen einer class gelten nicht als gleich, es sei denn, die class definiert spezielle Rich-Comparison-Methoden, die das Standardvergleichsverhalten von object anpassen.
Das Anpassen über rich comparisons wird in einer Folgeübung behandelt.
Weitere (viel) mehr Details zu diesem Thema findest du unter Wertvergleiche in der Python-Dokumentation.
Numerische Typen bilden (größtenteils) eine Ausnahme von dieser Regel zur Typübereinstimmung.
Ein integer kann als gleich einem float angesehen werden (oder ein octal als gleich einem hexadecimal), solange die Typen für den Vergleich implizit konvertiert werden können.
Für die anderen numerischen Typen in der Python-Standardbibliothek (complex, decimal, fractions) sind Vergleichsoperatoren dort definiert, wo sie „Sinn ergeben" (wo eine implizite Konvertierung das Ergebnis nicht verändert), lösen aber einen TypeError aus, wenn die zugrunde liegenden Objekte nicht genau genug für einen Vergleich konvertiert werden können.
Weitere Informationen zu den Regeln, die Python für die numerische Konvertierung verwendet, findest du unter arithmetische Konvertierungen in der Python-Dokumentation.
>>> import fractions
# A string cannot be converted to an int.
>>> 17 == '17'
False
# An int can be converted to float for comparison.
>>> 17 == 17.0
True
# The fraction 6/3 can be converted to the int 2
# The int 2 can be converted to 0b10 in binary.
>>> 6/3 == 0b10
True
# An int can be converted to a complex number with a 0 imaginary part.
>>> 17 == complex(17)
True
# The fraction 2/5 can be converted to the float 0.4
>>> 0.4 == 2/5
True
>>> complex(2/5, 1/2) == complex(0.4, 0.5)
True
Jeder geordnete Vergleich einer Zahl mit einem NaN-Typ (keine Zahl) ist False.
Ein verwirrender Nebeneffekt von Pythons NaN-Definition ist, dass NaN niemals gleich NaN ist.
>>> x = float('NaN')
>>> 3 < x
False
>>> x < 3
False
# NaN never compares equal to NaN
>>> x == x
False
Anders als Zahlen werden Strings (str) lexikografisch verglichen, anhand ihrer einzelnen Unicode-Codepunkte (das Ergebnis davon, jeden Codepunkt im str an die eingebaute Funktion ord() zu übergeben, die ein int zurückgibt).
Wenn alle Codepunkte in beiden Strings übereinstimmen und in derselben Reihenfolge sind, gelten die beiden Strings als gleich.
Dieser Vergleich erfolgt „paarweise": erstes mit erstem, zweites mit zweitem usw.
In Python 3.x können str und bytes nicht direkt konvertiert oder verglichen werden.
>>> 'Python' > 'Rust'
False
>>> 'Python' > 'JavaScript'
True
# Examples with Mandarin.
# hello < goodbye
>>> '你好' < '再见'
True
# ord() of first characters
>>> ord('你'), ord('再')
(20320, 20877)
# ord() of second characters
>>> ord('好'), ord('见')
(22909, 35265)
# And with Korean words.
# Pretty < beautiful.
>>> '예쁜' < '아름다운'
False
>>> ord('예'), ord('아')
(50696, 50500)
Vergleichsoperatoren können beliebig verkettet werden, das heißt, sie lassen sich in jeder Kombination und beliebiger Länge verwenden.
Beachte, dass die Auswertung eines Ausdrucks von left nach right erfolgt.
Zum Beispiel ist x < y <= z äquivalent zu x < y and y <= z, außer dass y nur einmal ausgewertet wird.
In beiden Fällen wird z überhaupt nicht ausgewertet, wenn sich x < y als False erweist.
Das nennt man oft short-circuit evaluation: Die Auswertung stoppt, sobald der Wahrheitswert des Ausdrucks bereits feststeht.
Short circuiting wird von verschiedenen booleschen Operatoren, Funktionen und auch von der Vergleichsverkettung in Python unterstützt.
Anders als in vielen anderen Programmiersprachen, darunter C, C++, C# und Java, haben verkettete Ausdrücke wie a < b < c in Python eine herkömmliche mathematische Interpretation und Vorrang.
>>> x = 2
>>> y = 5
>>> z = 10
>>> x < y < z
True
>>> x < y > z
False
>>> x > y < z
False
Die Operatoren is und is not prüfen die Identität eines Objekts, im Gegensatz zum Wert eines Objekts.
Die Identität eines Objekts ändert sich nach seiner Erzeugung nie und lässt sich mit der Funktion id() ermitteln.
<apple> is <orange> ergibt True, wenn und nur wenn id(<apple>) == id(<orange>) gilt.
<apple> is not <orange> liefert das Gegenteil.
Aufgrund ihres Singleton-Status sollten None und NotImplemented immer mit is und is not mit anderen Objekten verglichen werden.
Weitere Details zu dieser Konvention findest du in der Python-Referenz zu Wertvergleichen und in PEP8.
>>> my_fav_numbers = [1, 2, 3]
>>> your_fav_numbers = my_fav_numbers
>>> my_fav_numbers is your_fav_numbers
True
# The returned id will differ by system and python version.
>>> id(my_fav_numbers)
4517478208
# your_fav_numbers is only an alias pointing to the original my_fav_numbers object.
# Assigning a new name does not create a new object.
>>> id(your_fav_numbers)
4517478208
>>> my_fav_numbers is not your_fav_numbers
False
>>> my_fav_numbers is not None
True
>>> my_fav_numbers is NotImplemented
False
Die Operatoren in und not in prüfen die Mitgliedschaft.
<fish> in <soup> ergibt True, wenn <fish> ein Mitglied von <soup> ist (wenn <fish> eine Teilmenge von <soup> ist oder darin enthalten ist), andernfalls ergibt es False.
<fish> not in <soup> liefert die Negation, also das Gegenteil von <fish> in <soup>.
Bei den Typen String und Byte ist <name> in <fullname> dann und nur dann True, wenn <name> ein Teilstring von <fullname> ist.
# A set of lucky numbers.
>>> lucky_numbers = {11, 22, 33}
>>> 22 in lucky_numbers
True
>>> 44 in lucky_numbers
False
# A dictionary of employee information.
>>> employee = {'name': 'John Doe',
'id': 67826, 'age': 33,
'title': 'ceo'}
# Checking for the membership of certain keys.
>>> 'age' in employee
True
>>> 33 in employee
False
>>> 'lastname' not in employee
True
# Checking for substring membership
>>> name = 'Super Batman'
>>> 'Bat' in name
True
>>> 'Batwoman' in name
False
In dieser Übung implementierst du einige Regeln von Blackjack, zum Beispiel wie das Spiel gespielt und gewertet wird.
Hinweis: In dieser Übung steht A für Ass, J für Bube, Q für Dame und K für König.
Joker werden aussortiert.
Es wird ein französisches Standardkartenspiel mit 52 Karten angenommen, aber in den meisten Varianten werden mehrere Decks zusammen für das Spiel gemischt.
Bei Blackjack entscheidet jeder Spieler selbst, ob ein Ass 1 oder 11 Punkte wert ist (mehr dazu später).
Bildkarten (J, Q, K) werden mit 10 Punkten gewertet, und jede andere Karte ist ihren „Pip“-Wert (ihren Zahlenwert) wert.
Definiere die Funktion value_of_card(<card>) mit dem Parameter card.
Die Funktion soll den numerischen Wert des übergebenen Karten-Strings zurückgeben.
Da ein Ass mehrere Werte annehmen kann (1 oder 11), soll diese Funktion den Wert einer Ass-Karte vorerst auf 1 festlegen.
Später implementierst du eine Funktion, die den Wert einer Ass-Karte anhand einer bestehenden Hand bestimmt.
>>> value_of_card('K')
10
>>> value_of_card('4')
4
>>> value_of_card('A')
1
Definiere die Funktion higher_card(<card_one>, <card_two>) mit den Parametern card_one und card_two.
Für die Wertung haben J, Q und K den Wert 10.
Die Funktion soll zurückgeben, welche Karte für die Wertung den höheren Wert hat.
Wenn beide Karten denselben Wert haben, gib beide zurück.
Beide Karten kannst du zurückgeben, indem du ein Komma in der return-Anweisung verwendest:
# Using a comma in a return creates a Tuple. Tuples will be covered in a later exercise.
>>> def returning_two_values(value_one, value_two):
return value_one, value_two
>>> returning_two_values('K', '3')
('K', '3')
Ein Ass kann mehrere Werte annehmen, deshalb legen wir A-Karten für diese Aufgabe auf den Wert 1 fest.
>>> higher_card('K', '10')
('K', '10')
>>> higher_card('4', '6')
'6'
>>> higher_card('K', 'A')
'K'
Wie bereits erwähnt, kann ein Ass entweder 1 oder 11 Punkte wert sein. Die Spieler versuchen, so nah wie möglich an 21 Punkte heranzukommen, ohne über 21 zu gehen (sich also zu überkaufen).
Definiere die Funktion value_of_ace(<card_one>, <card_two>) mit den Parametern card_one und card_two. Das sind zwei Karten, die bereits auf der Hand liegen, bevor eine Ass-Karte dazukommt.
Deine Funktion muss entscheiden, ob das kommende Ass den Wert 1 oder den Wert 11 bekommt, und diesen Wert zurückgeben.
Denk daran: Der Wert der Hand mit dem Ass muss so hoch wie möglich sein, ohne über 21 zu gehen.
Hinweis: Wenn bereits ein Ass auf der Hand liegt, dann wäre der Wert für das kommende Ass 1.
>>> value_of_ace('6', 'K')
1
>>> value_of_ace('7', '3')
11
Wenn ein Spieler als erste zwei Karten ein Ass (A) und eine Zehnerkarte (10, K, Q oder J) bekommt, dann hat er 21 Punkte.
Das nennt man eine Blackjack-Hand.
Definiere die Funktion is_blackjack(<card_one>, <card_two>) mit den Parametern card_one und card_two. Das sind zwei Karten.
Stelle fest, ob die Zwei-Karten-Hand ein Blackjack ist, und gib den booleschen Wert True zurück, wenn ja, sonst False.
Hinweis: Die Berechnung des Punktestands kann auf viele Arten erfolgen. Wenn möglich, möchten wir aber, dass du prüfst, ob ein Ass und eine Zehnerkarte auf der Hand liegen (oder an einer bestimmten Position), statt die Handwerte zu summieren.
>>> is_blackjack('A', 'K')
True
>>> is_blackjack('10', '9')
False
Wenn die ersten beiden Karten einer Hand denselben Wert haben (zum Beispiel zwei Sechsen oder eine Q und ein K), kann ein Spieler sie als zwei getrennte Hände behandeln.
Das nennt man „Paare aufteilen“.
Definiere die Funktion can_split_pairs(<card_one>, <card_two>) mit den Parametern card_one und card_two. Das sind zwei Karten.
Stelle fest, ob diese Zwei-Karten-Hand in zwei Paare aufgeteilt werden kann.
Wenn die Hand aufgeteilt werden kann, gib den booleschen Wert True zurück, sonst False
>>> can_split_pairs('Q', 'K')
True
>>> can_split_pairs('10', 'A')
False
Wenn die ursprünglichen zwei ausgeteilten Karten zusammen 9, 10 oder 11 Punkte ergeben, kann ein Spieler einen zusätzlichen Einsatz in Höhe seines ursprünglichen Einsatzes platzieren. Das nennt man „Verdoppeln“.
Definiere die Funktion can_double_down(<card_one>, <card_two>) mit den Parametern card_one und card_two. Das sind zwei Karten.
Stelle fest, ob die Zwei-Karten-Hand „verdoppelt“ werden kann, und gib den booleschen Wert True zurück, wenn ja, sonst False.
>>> can_double_down('A', '9')
True
>>> can_double_down('10', '2')
False
Melde dich bei Exercism an, um Python mit 17 Konzepte146 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.