Python-Überblick und Syntax für JS/TS-Entwickler
Track Python · PCAP-Fundament · ca. 40 Min.
Worum es geht
Die Syntax von Python ist schnell gelernt, aber an etwa einem Dutzend Stellen verhält sie sich anders als JS/TS: Blöcke per Einrückung (indentation), “falsch” ist mehr als in JS, and/or liefern Operanden statt true/false, // rundet nach unten, und Type Hints prüft zur Laufzeit niemand. Laut Glossar entstehen die meisten Anfängerfehler aus der JS-Welt bei Scope, Veränderbarkeit und Gleichheit. Die Funktions-Themen (Default-Falle, Scope, Closures) hast du schon in Lektion 01, hier geht es um den Rest der Grundsyntax, den die PCAP ständig voraussetzt.
Ablauf: erst die Übersetzungstabelle, dann fünf kleine Schritte mit lauffähigem Code, dann fünf Übungen.
Von JS/TS her gedacht
| Thema | JS/TS | Python | Stolperfalle |
|---|---|---|---|
| Blöcke | { } |
Einrückung (4 Leerzeichen) und : |
falsche Einrückung ist ein IndentationError |
| Kein Wert | null, undefined |
nur None |
prüfen mit x is None |
| Boolesche Werte | true, false |
True, False |
Großschreibung zählt |
| Logik | &&, \|\|, ! |
and, or, not |
liefern einen der Operanden, nicht zwingend True/False |
| Gleichheit | === |
== (Wert), is (selbes Objekt) |
is nicht für Zahlen und Strings benutzen |
| Ternary | a ? b : c |
b if a else c |
Reihenfolge ist anders |
| Länge | .length |
len(x) |
Funktion statt Eigenschaft |
| Division | / ergibt Kommazahl |
/ ergibt immer float, // ist Ganzzahldivision |
-7 // 2 ist -4 |
| Potenz | ** |
** |
^ ist XOR |
| String plus Zahl | "1" + 1 ergibt "11" |
"1" + 1 ist ein TypeError |
Python ist streng typisiert |
| Typen | TS prüft beim Kompilieren | Type Hints werden zur Laufzeit ignoriert | die PCAP fragt Type Hints nicht ab |
Der größte Gedankenwechsel in einem Bild: Dieselbe Prüfung, zwei Sprachen.
// TypeScript: der Compiler weist den Aufruf ab
function greet(name: string, times: number = 1): string {
return ("Hallo " + name + "\n").repeat(times);
}
greet(42); // Compile-FehlerDer Fehler kommt erst im Rumpf, bei "Hallo " + 42. Mehr dazu in Schritt 5.
Konzept in kleinen Schritten
Schritt 1: Einrückung, Kommentare, dynamisch und streng
- Einrückung (indentation): Ein Block beginnt nach einem Doppelpunkt und endet, wenn die Einrückung zurückspringt. Üblich sind 4 Leerzeichen, Tabs und Leerzeichen nie mischen.
- Kommentar und Docstring:
# Kommentargeht bis zum Zeilenende. Ein String direkt am Anfang einer Funktion, Klasse oder Datei ist ein Docstring und über__doc__abrufbar. - Dynamisch typisiert (dynamically typed): Der Wert hat den Typ, nicht die Variable.
x = 1und danachx = "a"ist erlaubt. - Streng typisiert (strongly typed): Python wandelt nicht heimlich um.
Es gibt weder const noch let: Eine Variable entsteht durch Zuweisung. Konstanten sind nur Konvention (MAX_SIZE).
Schritt 2: Wahrheit, Logik, Gleichheit
Truthiness: Als falsch (falsy) gelten None, False, 0, 0.0, "", [], (), {} und set(). Alles andere ist wahr. Achtung: bool("False") ist True, weil der String nicht leer ist.
and und or werten per Kurzschluss (short-circuit) aus und liefern den Operanden selbst:
Die Regel zum Merken: or gibt den ersten wahren Operanden, and den ersten falschen, und sonst jeweils den letzten.
Gleichheit: == vergleicht Werte, is fragt, ob es dasselbe Objekt ist. Nutze is praktisch nur für None. Ein Ternary schreibt sich wert_wenn_wahr if bedingung else wert_wenn_falsch. Verkettete Vergleiche (chained comparisons) sind gültig: 1 < x < 5 bedeutet 1 < x and x < 5.
Schritt 3: Arithmetik und Zuweisung
/liefert immerfloat.//rundet zum kleineren Wert ab (-7 // 2ist-4).%ist Modulo (-7 % 2ist1).divmod(a, b)liefert beides als Tupel.- Vorrang:
**ist rechtsassoziativ (right-associative),2 ** 3 ** 2ist2 ** 9.-2 ** 2ist-4, weil**stärker bindet als das Minus. round(2.5)ergibt2,round(3.5)ergibt4(zur nächsten geraden Zahl).0.1 + 0.2 == 0.3istFalse, wie in JS.
Mehrfachzuweisung und Unpacking sparen Hilfsvariablen. Das kennst du als Destructuring:
// TypeScript
let [a, b] = [1, 2];
[a, b] = [b, a];
const [first, ...rest] = [1, 2, 3];Schritt 4: Schleifen, print und input
for x in iterable,while bedingung.range(start, stop, step)hat ein exklusives Ende.enumerate(it)liefert Index und Wert,zip(a, b)läuft paarweise.breakbeendet,continuespringt zum nächsten Durchlauf,passist ein Platzhalter für einen leeren Block.elsean Schleifen: Derelse-Block einerfor- oderwhile-Schleife läuft nur, wenn die Schleife nicht mitbreakverlassen wurde. Das gibt es in JS nicht.
print(a, b, sep="-", end="!") steuert Trennzeichen und Zeilenende (Standard: Leerzeichen und \n). input() liefert immer einen str, für Zahlen brauchst du int(input()). input läuft im Browser nicht sinnvoll, deshalb gibt es dazu hier keine Übung. Und: int("3.5") wirft einen ValueError.
Schritt 5: Type Hints sind nur Hinweise
Type Hints (name: str, -> str) stehen in __annotations__, werden aber zur Laufzeit nicht geprüft. Das ist der größte Unterschied zu TypeScript. Prüfen musst du selbst (isinstance) oder mit einem externen Werkzeug vor dem Lauf. Die PCAP fragt Type Hints laut Glossar nicht ab.
Hier wirft nichts, weil "ab" * 2 gültig ist. Das Programm läuft mit “falschem” Typ einfach weiter.
Falle: die Prüfungs- und Praxisklassiker
orundandliefern Operanden:0 or "x"ist"x", nichtTrue. Undbool("False")istTrue.-7 // 2ist-4, nicht-3.//rundet nach unten, nicht zur Null.-2 ** 2ist-4, weil**vor dem Minus bindet.isstatt==:a is bfragt nach demselben Objekt. Nur fürNoneverwenden.len(x) / 2als Index:/liefert einenfloat, undliste[2.0]ist einTypeError. Dafür gibt es//.- Schleifen-
else: gehört zur Schleife, nicht zu einemif. Es läuft, wenn die Schleife ohnebreakzu Ende kam (typisch: Suche ohne Treffer). - Type Hints schützen nicht:
greet(42)wird angenommen.
Übungen
Übung 1: Arithmetik vorhersagen
Trage ein Tupel mit den sechs Ergebnissen ein, in dieser Reihenfolge:
(2 ** 3 ** 2, -2 ** 2, -7 // 2, -7 % 2, round(2.5), 7 / 2)Bei ** zählt, wer zuerst gerechnet wird (von rechts oder links?) und ob das Minus davor oder danach kommt. Bei // und % mit negativen Zahlen: Wohin rundet Python? Und round hat eine Besonderheit bei genau .5.
antwort = (512, -4, -4, 1, 2, 3.5)
antwortÜbung 2: Wahrheit und Logik vorhersagen
Trage wieder ein Tupel mit den sechs Ergebnissen ein. Achte genau darauf, was zurückkommt, nicht nur ob es wahr oder falsch ist:
(0 or "x", "a" and "b", "" and "b", [] or None, bool("False"), bool([0]))Welche Operanden gelten als falsch? Dann: Wen von beiden gibt or zurück, wen and, und wann den jeweils anderen? Bei bool(...) zählt nur, ob der Container oder String leer ist, nicht sein Inhalt.
antwort = ("x", "b", "", None, True, True)
antwortÜbung 3: Schleifen-else nutzen
Die Funktion ist_prim(n) soll True liefern, wenn n eine Primzahl ist (nur durch 1 und sich selbst teilbar, die kleinste ist 2), sonst False. Fülle die Lücken. Die Schleife soll mit else arbeiten, also ohne Merker-Variable.
Das Ende von range ist exklusiv: Der letzte Teiler, den du prüfen willst, muss noch dabei sein. Und wann läuft der else-Zweig einer Schleife, in welchem Fall also hast du keinen Teiler gefunden? Prüfe dein range an den Zahlen 4 und 9.
def ist_prim(n):
if n < 2:
return False
for teiler in range(2, n):
if n % teiler == 0:
return False
else:
return True
ist_primÜbung 4: JS-Reflexe finden
Dieser Code stammt von jemandem, der JS im Kopf hat. mitte(werte) soll das mittlere Element liefern (bei gerader Länge das hintere der beiden mittleren) und bei einer leeren Liste None. Zwei Dinge sind falsch. Repariere sie.
Erstes Problem: Was fragt is eigentlich, und ist eine frisch geschriebene [] dasselbe Objekt wie deine Liste? Zweites Problem: Welchen Typ liefert / in Python, und was verlangt ein Listenindex?
def mitte(werte):
if len(werte) == 0:
return None
return werte[len(werte) // 2]
mitteÜbung 5: Type Hints, was passiert wirklich?
Gegeben ist dieser Code:
def greet(name: str, times: int = 1) -> str:
return ("Hallo " + name + "\n") * times
greet(42)Was passiert? Trage "A", "B", "C" oder "D" ein.
- A: Python wirft schon beim Aufruf einen
TypeError, weil 42 keinstrist. - B: Der Aufruf läuft durch, Python macht aus 42 selbst den Text “Hallo 42”.
- C: Der Aufruf wird angenommen, erst die Verkettung im Rumpf wirft einen
TypeError. - D: Der Aufruf wird angenommen und liefert
None, weil der Typ nicht zur Angabe passt.
Wer prüft name: str beim Aufruf? Und wenn niemand prüft: Was macht dann "Hallo " + 42 im Rumpf, und wandelt Python wie JS heimlich um?
antwort = "C"
antwortMerksatz und Prüfstein
Merksatz: In Python entscheiden Einrückung und Wahrheitswert-Regeln über den Ablauf, and/or liefern Operanden, und Type Hints sind nur Hinweise, die zur Laufzeit niemand prüft.
Prüfstein (offene Frage): Erkläre in eigenen Worten, warum 0 or "x" den Wert "x" liefert und "" and "b" den leeren String, und warum greet(42) trotz name: str nicht sofort abgelehnt wird. Was würdest du in TypeScript an derselben Stelle bekommen?
Quelle: quellen/python-glossar-pcap-pcpp1.md, Abschnitte “Python vs. JS/TS auf einen Blick” und “Syntax und Grundlagen”. Hinweis: __annotations__, __doc__-Beispiele, .repeat und die Primzahl-Aufgabe stammen nicht aus der Quelle, wurden aber mit Python 3.13 ausgeführt (bitte prüfen, ob __annotations__ in der PCAP geprüft wird).