This commit is contained in:
Amalia Sucipto committed 2026-11-05 14:23:12 +01:00
commit 57f043f977
12 files changed
+376

No files matched your search

+8
View File
@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.venv" />
<excludeFolder url="file://$MODULE_DIR$/.venv1" />
</content>
<orderEntry type="jdk" jdkName="Python 3.13 (Funktional)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
+9
View File
@@ -0,0 +1,9 @@
"""Reeborg hat im ersten Semester ziemlich viele Schritte gebraucht, um eine Zahl zu verdoppeln. Wir schaffen es
inzwischen in einer Zeile, zu einer Liste von Zahlen numbers = [1, 2, 3, 4, 5] eine Liste mit den doppelten
Werten zu erzeugen, wenn wir map und lambda benutzen. Wie?"""
numbers = [1, 2, 3, 4, 5]
doubled_numbers = map(lambda x: x*2, numbers)
print(doubled_numbers)
+14
View File
@@ -0,0 +1,14 @@
"""Für Posts auf Social Media möchten wir alle Wörter einer Liste in Großbuchstaben umwandeln. Ein einzelner String
lässt sich mit der Methode upper in Großbuchstaben konvertieren:
print("sad!".upper()) # -> SAD!
Für die Liste words = ["Hofmann", "was", "right", "about", "something"] verwenden wir wieder map und
lambda.
Übrigens: Um die Liste anschließend zu einem String mit Leerzeichen zwischen den Wörtern zu verbinden, ist der
„most pythonic way“ folgender:
sentence = " ".join(words)"""
words = ["Hofmann", "was", "right", "about", "something"]
all_caps = map(lambda x: x.upper(), words)
sentence = " ".join(all_caps)
print(sentence)
+7
View File
@@ -0,0 +1,7 @@
"""Gerade Zahlen (P)
Wir haben eine Liste mit ganzen Zahlen, z.B. numbers = list(range(1, 21)). Wie erhalten wir mit filter
daraus eine Liste, die nur die geraden Zahlen enthält?"""
numbers = list(range(1, 21))
even_numbers = filter(lambda x: x % 2 == 0, numbers)
print(list(even_numbers))
+9
View File
@@ -0,0 +1,9 @@
"""Gegeben ist words = ["Apfel", "Banane", "Kirsche", "Kiwi", "Melone"].
Wir benötigen eine Summe der Wortlänge aller Wörter, die mit „K“ beginnen. Geht das in einer Zeile, wenn mit
sum([1, 2, 3]) # -> 6?
die Summe aller Zahlen eines Iterators (z.B. Liste) berechnet werden kann? """
words = ["Apfel", "Banane", "Kirsche", "Kiwi", "Melone"]
result = sum(map(lambda word: len(word), filter(lambda word: word[0] == "K", words)))
print(result)
+8
View File
@@ -0,0 +1,8 @@
"""Produkt (P)
Wir berechnen mit Hilfe von reduce das Produkt der Zahlen in der Liste numbers = [1, 2, 3, 4, 5]. """
from functools import reduce
numbers = [1, 2, 3, 4, 5]
result = reduce(lambda x, y: x*y, numbers)
print(result)
+31
View File
@@ -0,0 +1,31 @@
"""Undo (P)
Schauen wir uns noch einmal die funktionale Version der Particle-Klasse aus dem Skript an. Implementieren Sie
diese nach und merken Sie sich bei einem update die Vorversion in einer Liste. Ergänzen Sie eine Methode undo,
die die jeweilige Vorversion zurückliefert. Wie könnte man ein Ausufern der Liste vermeiden (und dann eben nur
ein paar Undos erlauben)? """
class Particle:
def __init__(self, position, velocity=(0, 0), acceleration=(0, 0)):
self.position = position
self.velocity = velocity
self.acceleration = acceleration
self.history = []
def update(self):
new_velocity = (self.velocity[0] + self.acceleration[0],
self.velocity[1] + self.acceleration[1])
new_position = (self.position[0] + new_velocity[0],
self.position[1] + new_velocity[1])
new_particle = Particle(new_position, new_velocity, self.acceleration)
new_particle.history = (self.history + [self])[-3:]
return new_particle
def undo(self):
if self.history:
return self.history[-1]
return self
+51
View File
@@ -0,0 +1,51 @@
import pygame
class Game:
def __init__(self, title, fps=60, size=(640, 400)):
self.title = title
self.fps = fps
self.size = size
self.clock = pygame.time.Clock()
self.dt = 0
self.screen = None
def init_game(self):
pygame.init()
pygame.display.set_caption(self.title)
self.screen = pygame.display.set_mode(self.size)
def game_loop(self):
while True:
# Berechnung der Zeitdifferenz seit dem letzten Frame
self.dt = self.clock.tick(self.fps) / 1000
if self.event_handling() == False:
break
if self.update_game() == False:
break
self.draw_game()
def exit_game(self):
pygame.quit()
def event_handling(self): # bleibt in der Unterklasse unverändert
for event in pygame.event.get():
if not self.handle_event(event):
return False
return True
def handle_event(self, event): # wird in der Unterklasse überschrieben
if event.type == pygame.QUIT:
return False
return True
def update_game(self):
return True
def draw_game(self):
pygame.display.flip()
def run(self):
self.init_game()
self.game_loop()
self.exit_game()
+145
View File
@@ -0,0 +1,145 @@
#!/usr/bin/env python3
"""Installiert die Abhängigkeiten aus pyproject.toml in die aktuelle Python-Umgebung.
Ersatz für "Install requirements" aus PyCharm, wenn das Projekt eine pyproject.toml
statt einer requirements.txt hat. Kein Build, keine besondere Projektstruktur nötig,
nur Standardbibliothek (Python >= 3.11).
Benutzung:
In PyCharm: Rechtsklick auf diese Datei -> Run 'install_dependencies'
Im Terminal (venv aktiv): python install_dependencies.py
Ohne Parameter wird ALLES installiert:
[project].dependencies + alle [project.optional-dependencies] + alle [dependency-groups]
Abweichendes Verhalten:
python install_dependencies.py --extra dev nur Basis + Extra "dev"
python install_dependencies.py --group test nur Basis + Gruppe "test"
python install_dependencies.py --no-main --group dev
python install_dependencies.py --list nur anzeigen, nichts installieren
python install_dependencies.py --write requirements.txt schreiben statt installieren
python install_dependencies.py --write -o reqs.txt
"""
from __future__ import annotations
import sys
if sys.version_info < (3, 11):
sys.exit("Dieses Skript braucht Python 3.11 oder neuer (tomllib). "
f"Aktuell: {sys.version.split()[0]}")
import argparse
import subprocess
import tempfile
import tomllib
from pathlib import Path
PROJECT_DIR = Path(__file__).resolve().parent
def resolve_group(groups: dict, name: str, seen: set[str] | None = None) -> list[str]:
"""Löst eine Dependency-Group inkl. {include-group = "..."} rekursiv auf."""
seen = set() if seen is None else seen
if name in seen:
raise ValueError(f"Zyklische include-group: {name}")
if name not in groups:
raise KeyError(f"Dependency-Group '{name}' nicht gefunden")
seen.add(name)
result: list[str] = []
for entry in groups[name]:
if isinstance(entry, str):
result.append(entry)
elif isinstance(entry, dict) and "include-group" in entry:
result.extend(resolve_group(groups, entry["include-group"], seen))
return result
def collect(data: dict, extras: list[str], groups: list[str], no_main: bool) -> list[str]:
project = data.get("project", {})
optional = project.get("optional-dependencies", {})
dep_groups = data.get("dependency-groups", {})
deps: list[str] = []
if not no_main:
deps.extend(project.get("dependencies", []))
for extra in extras:
if extra not in optional:
raise KeyError(f"Optional-Dependency '{extra}' nicht gefunden")
deps.extend(optional[extra])
for group in groups:
deps.extend(resolve_group(dep_groups, group))
# Duplikate entfernen, Reihenfolge behalten
return list(dict.fromkeys(d.strip() for d in deps if d.strip()))
def main() -> int:
p = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
p.add_argument("-p", "--pyproject", type=Path, default=PROJECT_DIR / "pyproject.toml",
help="Pfad zur pyproject.toml (Standard: neben diesem Skript)")
p.add_argument("--extra", action="append", default=None,
help="nur diese optional-dependencies (mehrfach möglich)")
p.add_argument("--group", action="append", default=None,
help="nur diese dependency-groups (mehrfach möglich)")
p.add_argument("--no-main", action="store_true", help="[project].dependencies weglassen")
p.add_argument("--list", action="store_true", help="Abhängigkeiten nur anzeigen")
p.add_argument("--write", action="store_true", help="requirements-Datei schreiben statt installieren")
p.add_argument("-o", "--output", type=Path, default=PROJECT_DIR / "requirements.txt",
help="Zieldatei für --write")
args = p.parse_args()
if not args.pyproject.exists():
print(f"{args.pyproject} nicht gefunden", file=sys.stderr)
return 1
data = tomllib.loads(args.pyproject.read_text(encoding="utf-8"))
all_extras = list(data.get("project", {}).get("optional-dependencies", {}))
all_groups = list(data.get("dependency-groups", {}))
# Ohne --extra/--group: alles. Mit einem davon: nur das Gewählte.
selective = args.extra is not None or args.group is not None
extras = (args.extra or []) if selective else all_extras
groups = (args.group or []) if selective else all_groups
try:
deps = collect(data, extras, groups, args.no_main)
except (KeyError, ValueError) as e:
print(f"Fehler: {e.args[0]}", file=sys.stderr)
print(f" Vorhandene --extra: {', '.join(all_extras) or '(keine)'}", file=sys.stderr)
print(f" Vorhandene --group: {', '.join(all_groups) or '(keine)'}", file=sys.stderr)
return 1
parts = ([] if args.no_main else ["Basis"]) + [f"extra:{e}" for e in extras] + [f"group:{g}" for g in groups]
print(f"Auswahl: {', '.join(parts) or '(nichts)'}")
if args.list:
print("\n".join(deps) or "(keine Abhängigkeiten)")
return 0
content = f"# Automatisch erzeugt aus {args.pyproject.name} – nicht von Hand bearbeiten\n" + "\n".join(deps) + "\n"
if args.write:
args.output.write_text(content, encoding="utf-8")
print(f"{len(deps)} Abhängigkeiten -> {args.output}")
return 0
if not deps:
print("Keine Abhängigkeiten gefunden – nichts zu tun.")
return 0
if sys.prefix == sys.base_prefix:
print("WARNUNG: Es ist kein virtuelles Environment aktiv – es wird in die globale "
f"Python-Installation installiert:\n {sys.prefix}", file=sys.stderr)
if sys.stdin.isatty() and input("Trotzdem fortfahren? [j/N] ").strip().lower() not in ("j", "ja", "y", "yes"):
return 1
with tempfile.NamedTemporaryFile("w", suffix=".txt", delete=False, encoding="utf-8") as tmp:
tmp.write(content)
tmp_path = Path(tmp.name)
try:
print(f"Installiere {len(deps)} Abhängigkeiten in {sys.prefix}\n")
return subprocess.call([sys.executable, "-m", "pip", "install", "-r", str(tmp_path)])
finally:
tmp_path.unlink(missing_ok=True)
if __name__ == "__main__":
raise SystemExit(main())
+6
View File
@@ -0,0 +1,6 @@
[project]
name = "Funktional"
version = "0.1.0"
dependencies = ["pygame-ce"]
[project.optional-dependencies]
dev = ["pytest", "ruff", "pytest-cov"]
+77
View File
@@ -0,0 +1,77 @@
"""Undo Doodle (P)
Programmieren Sie das Zeichenprogramm wie im Skript beschrieben auf Basis Ihrer Klasse Game. Der Zustand (Liste
von Strichen) und die Historie werden nie verändert, sondern bei jedem Strich neu erzeugt."""
import pygame
from game import Game
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
class Doodle(Game):
def __init__(self):
super().__init__("drawing game!")
self.points = []
self.line = []
self.history = []
self.mouse_pressed = False
def handle_event(self, event):
if not super().handle_event(event):
return False
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
self.mouse_pressed = True
self.points = [event.pos]
if event.type == pygame.MOUSEMOTION:
if self.mouse_pressed:
self.points = self.points + [event.pos]
if event.type == pygame.MOUSEBUTTONUP:
if event.button == 1 and self.mouse_pressed:
self.mouse_pressed = False
self.points = self.points + [event.pos]
self.history = self.history + [self.line]
self.line = self.line + [self.points]
self.points = []
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_z:
self.undo()
return True
def undo(self):
if self.history:
self.line = self.history[-1]
self.history = self.history[:-1]
def draw_game(self):
self.screen.fill(WHITE)
for line in self.line:
if len(line) >=2:
pygame.draw.lines(self.screen, BLACK, False, line, 2)
elif len(line) ==1:
pygame.draw.circle(self.screen, BLACK, line[0],2, 2)
if len(self.points) >= 2:
pygame.draw.lines(
self.screen, BLACK, False, self.points, 2
)
elif len(self.points) == 1:
pygame.draw.circle(
self.screen, BLACK, self.points[0], 2
)
pygame.display.flip()
if __name__ == "__main__":
doodle = Doodle()
doodle.run()