1. Tooling: uv & Projektsetup
uv ist ein moderner, schneller Ersatz für
pip,
venv,
conda und ähnliche Tools.
Ein einziges Werkzeug für alles.
# Create new project
uv init my-project
cd my-project
# Install packages
uv add numpy matplotlib
# Run script
uv run script.py
Die pyproject.toml
Jedes Projekt hat eine pyproject.toml.
Sie definiert die Python-Version und alle Abhängigkeiten. uv verwaltet auch Python selbst:
wenn die geforderte Version fehlt, wird sie automatisch heruntergeladen.
[project]
name = "traffic-jam"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
"matplotlib>=3.10",
]
2. .py-Dateien statt Notebooks
Jupyter ist nur eine Schicht über Python. Wir arbeiten direkt mit dem, was Jupyter im Hintergrund tut.
- Code in einzelnen Zellen
- Zellen in beliebiger Reihenfolge ausführbar
- Versteckter Zustand: Variablen leben im Hintergrund
- Schwer reproduzierbar: Ergebnis hängt von der Reihenfolge ab
- Code in einer Datei, von oben nach unten
- Jeder Lauf startet bei null, kein versteckter Zustand
- Reproduzierbar:
uv run script.pyliefert immer dasselbe Ergebnis - Saubere Git-Diffs, besseres Tooling für AI-Assistenten
3. Variablen & Typen
Python erkennt den Typ automatisch aus dem zugewiesenen Wert. Keine Typdeklaration nötig.
| Typ | Beispiel | Beschreibung |
|---|---|---|
int |
x = 42 |
Ganzzahl |
float |
pi = 3.14 |
Gleitkommazahl |
str |
name = "Hallo" |
Text |
bool |
active = True |
Wahrheitswert |
list |
numbers = [1, 2, 3] |
Liste (geordnet, veränderbar) |
road_length = 230.0
n_vehicles = 22
spacing = road_length / n_vehicles
# f-strings for text formatting
print(f"{n_vehicles} vehicles on {road_length} m")
4. Kontrollstrukturen
Einrückung ist Logik:
Python verwendet Einrückung statt {},
um Codeblöcke zu definieren. Falsche Einrückung führt zu Fehlern.
Verzweigungen
speed = 25.0
if speed > 30.0:
print("Too fast!")
elif speed < 5.0:
print("Almost stopped")
else:
print("Normal flow")
Schleifen
# for loop
for i in range(5):
print(f"Step {i}")
# while loop
t = 0.0
while t < 10.0:
t += 0.1
List Comprehensions
# Instead of:
squares = []
for x in range(10):
squares.append(x ** 2)
# Better:
squares = [x ** 2 for x in range(10)]
# With condition:
even = [x for x in range(20) if x % 2 == 0]
5. Funktionen
def optimal_velocity(headway: float, v_max=9.25, d_min=4.0, d_max=25.0) -> float:
"""Calculate desired velocity based on headway distance."""
if headway <= d_min:
return 0.0
elif headway >= d_max:
return v_max
return v_max * (headway - d_min) / (d_max - d_min)
headway: float dokumentiert den erwarteten Typ, wenn kein Defaultwert vorhanden ist. Bei Defaults wie v_max=9.25 ist der Typ offensichtlich.""" beschreiben, was die Funktion tut. Immer auf Englisch. Pflicht in unseren Projekten.6. Klassen
Klasse = Bauplan | Objekt = konkretes Exemplar | Methode = eine Funktion, die zu einer Klasse gehört
class Dog:
"""A dog with a name and energy level."""
def __init__(self, name: str, energy=100):
self.name = name
self.energy = energy
def bark(self):
"""Bark and lose some energy."""
self.energy -= 10
print(f"{self.name}: Woof!")
rex = Dog("Rex")
rex.bark() # Rex: Woof!
print(rex.energy) # 90
luna = Dog("Luna", energy=50)
luna.bark() # Luna: Woof!
print(luna.energy) # 40
@dataclass
@dataclass generiert
__init__,
__repr__ und
__eq__ automatisch.
Weniger Boilerplate, gleiche Funktionalität.
from dataclasses import dataclass
@dataclass
class Vehicle:
position: float
velocity: float
7. Module & Imports
# Standard library
import math
from pathlib import Path
from dataclasses import dataclass
# External packages (uv add ...)
import numpy as np
import matplotlib.pyplot as plt
my-project/
├── main.py # entry point
├── model.py # model classes
└── pyproject.toml # project file (uv)
# in main.py:
from model import Vehicle, TrafficModel
Immer uv add statt
pip install verwenden,
damit Abhängigkeiten in pyproject.toml landen.
8. Guter Stil
Alles auf Englisch
Variablen, Funktionen, Klassen, Kommentare, Docstrings: alles auf Englisch. Code wird international gelesen, geteilt und von englischsprachigen Tools verarbeitet.
Gute Variablennamen
a = 230.0
b = 22
x = a / b
l = []
for i in range(b):
l.append(i * x)
road_length = 230.0
n_vehicles = 22
spacing = road_length / n_vehicles
positions = []
for i in range(n_vehicles):
positions.append(i * spacing)
Zusammenfassung
- Type Hints wo der Typ nicht offensichtlich ist
- f-Strings statt
.format() @dataclassfür Datenklassen- List Comprehensions
- Docstrings für Funktionen, Methoden und Klassen
- Globale Variablen
from module import *- Magic Numbers ohne Namen
- Redundante Type Hints:
x: int = 5 - Deutsche Variablennamen