For AI agents: use /llms.txt for the Nakafa content index.
Python unterstützt mehrere Paradigmen: Prozedurale, funktionale und objektorientierte Stile können nebeneinander bestehen. Laufzeitwerte wie Zahlen, Funktionen, Klassen und Module sind Objekte mit Typ, Identität und Wert.
Objekte können über ihren Typ Attribute und Operationen anbieten. Dieses einheitliche Modell ermöglicht es, eine Funktion in einer Liste zu speichern, eine Klasse an eine andere Funktion zu übergeben und Methoden an Zahlen aufzurufen, ohne jedes Programm objektorientiert entwerfen zu müssen.
In einem prozeduralen Stil wird ein Programm um Operationen und einen expliziten Datenfluss organisiert. Datenstrukturen und die Funktionen, die sie erhalten, können getrennt bleiben, auch wenn die Sprache zusätzlich Klassen unterstützt.
#include <stdio.h>
// Beispiel für einen prozeduralen Ansatz in C
struct ParkSystem {
int max;
int occ;
};
int occupy(struct ParkSystem* ps) {
if (ps->max <= ps->occ) {
return -1;
}
ps->occ++;
return 0;
}
void leave(struct ParkSystem* ps) {
if (ps->occ > 0) {
ps->occ--;
}
}
int main() {
struct ParkSystem ps = {100, 0};
occupy(&ps);
printf("%d %d", ps.max, ps.occ);
return 0;
}Hier speichert das C-struct den Parkzustand und jede Funktion erhält einen Zeiger darauf. Diese Organisation ist prozedural. Sie bedeutet nicht, dass jede prozedurale Funktion ihre Eingabe verändern muss.
In einem objektorientierten Stil kann eine Klasse zusammengehörigen Zustand und Verhalten hinter einer Schnittstelle bündeln. Attribute beschreiben den Objektzustand, Methoden die Operationen, die ihn verwenden oder verändern.
# Beispiel für einen objektorientierten Ansatz in Python
class ParkSystem:
def __init__(self, max_capacity):
self.max = max_capacity
self.occ = 0
def occupy(self):
if self.max <= self.occ:
return -1
self.occ += 1
return 0
def leave(self):
if self.occ > 0:
self.occ -= 1
# Verwendung
ps = ParkSystem(100)
ps.occupy()
print(f"Max: {ps.max}, Occupied: {ps.occ}")Die Python-Version bündelt Parkinvarianten und Operationen in einer Klasse. Diese Grenze schützt gültigen Zustand aber nur, wenn ihre Methoden Eingaben prüfen und veränderliche Interna nicht unbedacht offenlegen.
Nehmen wir als Beispiel ein Parksystem, um das Konzept von Objekten zu verstehen. In der realen Welt weist ein Parksystem Merkmale wie die maximale Kapazität und die Anzahl der belegten Stellplätze auf. Dieses System kann auch Aktionen wie das Akzeptieren ein- oder ausfahrender Autos durchführen.
class ParkingSystem:
def __init__(self, capacity):
"""Parksystem mit bestimmter Kapazität initialisieren"""
if capacity <= 0:
raise ValueError("Die Kapazität muss positiv sein")
self.capacity = capacity
self.vehicles = [] # Liste der geparkten Fahrzeuge
def park_vehicle(self, vehicle_plate):
"""Methode zum Parken eines Fahrzeugs"""
if vehicle_plate in self.vehicles:
return f"Fahrzeug {vehicle_plate} ist bereits geparkt"
if len(self.vehicles) >= self.capacity:
return f"Parkplatz voll! {vehicle_plate} kann nicht geparkt werden"
self.vehicles.append(vehicle_plate)
return f"Fahrzeug {vehicle_plate} erfolgreich geparkt"
def exit_vehicle(self, vehicle_plate):
"""Methode zum Verlassen des Parkplatzes"""
if vehicle_plate in self.vehicles:
self.vehicles.remove(vehicle_plate)
return f"Fahrzeug {vehicle_plate} hat den Parkplatz verlassen"
else:
return f"Fahrzeug {vehicle_plate} nicht gefunden"
def get_status(self):
"""Methode zum Anzeigen des Parkstatus"""
occupied = len(self.vehicles)
available = self.capacity - occupied
return {
'capacity': self.capacity,
'occupied': occupied,
'available': available,
'vehicles': tuple(self.vehicles)
}
def is_full(self):
"""Methode zur Überprüfung, ob der Parkplatz voll ist"""
return len(self.vehicles) >= self.capacity
# Beispielverwendung
parking = ParkingSystem(5)
print(parking.park_vehicle("B 1234 CD"))
print(parking.park_vehicle("B 5678 EF"))
print(parking.get_status())
print(parking.is_full())„Alles ist ein Objekt“ bedeutet, dass Python Laufzeitwerte über ein gemeinsames Objektmodell behandelt. Welche Attribute und Methoden verfügbar sind, hängt weiterhin vom jeweiligen Typ ab.
# Zahlen in Python sind Objekte
number = 42
# Zahlen haben Methoden
print(number.bit_length()) # Methode zur Berechnung der Bitlänge
print(number.__add__(8)) # Additionsmethode (wie Zahl + 8)
# Float-Zahlen sind ebenfalls Objekte
price = 15.75
print(price.is_integer()) # Methode zur Überprüfung, ob es sich um eine ganze Zahl handelt
print(price.as_integer_ratio()) # Methode zur Umrechnung in ein Verhältnis
# Sogar die Ergebnisse mathematischer Operationen sind Objekte
result = 10 + 5
print(type(result)) # <class 'int'>
print(dir(result)) # Alle verfügbaren Methoden anzeigen# Zeichenfolgen in Python sind sehr leistungsstarke Objekte
message = "Python zu lernen macht Spaß"
# Strings haben viele nützliche Methoden
print(message.upper()) # PYTHON LERNEN MACHT SPASS
print(message.lower()) # Python lernen macht Spaß
print(message.title()) # Python zu lernen macht Spaß
print(message.count('N')) # Zähle den Buchstaben „n“
print(message.replace('Python', 'Programming')) # Wort ersetzen
# Methoden zur Überprüfung
email = "user@example.com"
print(email.endswith('.com')) # True
print(email.startswith('user')) # True
print(email.find('@')) # Position des „@“-Zeichens
# Methoden zur Formatierung
name = "alice"
age = 25
formatted = "Name: {}, Alter: {}".format(name.title(), age)
print(formatted)
# String teilen und verbinden
words = message.split() # In Wortliste aufteilen
print(words)
rejoined = " ".join(words) # Kommt wieder zusammen
print(rejoined)# Listen in Python sind dynamische Objekte
fruits = ["Apfel", "Orange", "Mango"]
# Listen verfügen über Methoden zur Datenmanipulation
fruits.append("Banane") # Am Ende hinzufügen
print(fruits)
fruits.insert(1, "Erdbeere") # An einer bestimmten Position hinzufügen
print(fruits)
fruits.remove("Orange") # Bestimmtes Element entfernen
print(fruits)
# Methoden zum Suchen und Sortieren
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
print(numbers.count(1)) # Vorkommen zählen
print(numbers.index(4)) # Position finden
numbers.sort() # Sortieren
print(numbers)
numbers.reverse() # Umgekehrte Reihenfolge
print(numbers)
# Listenkomprehension - die idiomatische Python-Variante
squares = [x**2 for x in range(1, 6)]
print(squares) # [1, 4, 9, 16, 25]
# Methoden für fortgeschrittene Operationen
original = [1, 2, 3]
copy_list = original.copy() # Kopie erstellen
original.extend([4, 5]) # Mehrere Elemente hinzufügen
print(f"Original: {original}")
print(f"Copy: {copy_list}")# Wörterbücher in Python sind flexible Objekte
student = {
"name": "Alice",
"age": 22,
"major": "Computer Science",
"gpa": 3.8
}
# Wörterbücher verfügen über Manipulationsmethoden
print(student.get("name")) # Wert sicher abrufen
print(student.get("height", "Unbekannt")) # Standardwert, wenn der Schlüssel nicht vorhanden ist
# Methoden zum Anzeigen von Wörterbuchinhalten
print(student.keys()) # Alle Schlüssel
print(student.values()) # Alle Werte
print(student.items()) # Schlüssel-Wert-Paare
# Methoden zur Aktualisierung und Manipulation
student.update({"semester": 6, "age": 23}) # Update multiple values
print(student)
# Pop-Methode zum Abrufen und Entfernen
gpa = student.pop("gpa")
print(f"GPA entfernt: {gpa}")
print(student)
# Dictionary comprehension
grades = {"Math": 85, "Physics": 92, "Chemistry": 78}
passed = {subject: grade for subject, grade in grades.items() if grade >= 80}
print(passed)
# Nested dictionary
university = {
"students": {
"CS": ["Alice", "Bob"],
"Math": ["Charlie", "Diana"]
},
"location": "Jakarta"
}
print(university["students"]["CS"])Auch Funktionen sind in Python Objekte. Deshalb kannst du sie wie andere Daten weitergeben, speichern und verwenden.
# Funktionen in Python sind erstklassige Objekte
def greet(name):
return f"Hello, {name}!"
def farewell(name):
return f"Goodbye, {name}!"
# Funktionen haben Attribute
print(greet.__name__) # Funktionsname
print(type(greet)) # <class 'function'>
# Funktionen können in Variablen gespeichert werden
my_function = greet
print(my_function("Alice")) # Hello, Alice!
# Funktionen können in Listen gespeichert werden
functions = [greet, farewell]
for func in functions:
print(func("Bob"))
# Als Parameter können Funktionen verwendet werden
def call_function(func, name):
return func(name)
result = call_function(greet, "Charlie")
print(result)
# Funktionen können von anderen Funktionen zurückgegeben werden
def get_greeting_function(language):
def english_greet(name):
return f"Hello, {name}!"
def indonesian_greet(name):
return f"Halo, {name}!"
if language == "english":
return english_greet
if language == "indonesian":
return indonesian_greet
raise ValueError(f"Nicht unterstützte Sprache: {language}")
# Verwendung der zurückgegebenen Funktion
greet_func = get_greeting_function("indonesian")
print(greet_func("Diana")) # Halo, Diana!
# Lambda-Funktionen sind ebenfalls Objekte
square = lambda x: x ** 2
print(type(square)) # <class 'function'>
print(square(5)) # 25Eine Klasse definiert, wie ihre Instanzen entstehen und wie gemeinsames Verhalten aufgelöst wird. Die Klasse selbst ist ebenfalls ein Objekt, während jede Instanz ihren eigenen Instanzzustand trägt.
# Klasse als Blaupause erstellen
class Student:
# Class attribute (shared by all instances)
university = "Universitas Indonesia"
def __init__(self, name, major, semester):
# Instanzattribute (für jede Instanz individuell)
self.name = name
self.major = major
self.semester = semester
self.courses = []
def add_course(self, course):
"""Methode zum Hinzufügen eines Kurses"""
self.courses.append(course)
return f"{self.name} nimmt Kurs {course}"
def get_info(self):
"""Methode, um Studenteninformationen zu erhalten"""
return {
'name': self.name,
'major': self.major,
'semester': self.semester,
'courses': self.courses,
'university': self.university
}
def __str__(self):
"""Spezielle Methode zur String-Darstellung"""
return f"Student({self.name}, {self.major})"
def __len__(self):
"""Spezielle Methode, um die Anzahl der Kurse zu ermitteln"""
return len(self.courses)
# Instanzen (Objekte) aus einer Klasse erstellen
student1 = Student("Alice", "Computer Science", 4)
student2 = Student("Bob", "Mathematics", 6)
# Jede Instanz ist ein Objekt mit Attributen und Methoden
print(student1.add_course("Python Programming"))
print(student1.add_course("Data Structures"))
print(student2.add_course("Calculus"))
print(student2.add_course("Linear Algebra"))
# Methoden nutzen
print(student1.get_info())
print(student2.get_info())
# Spezielle Methoden (__str__ und __len__)
print(student1) # Student(Alice, Computer Science)
print(len(student1)) # 2 (Anzahl Kurse)
# Instanzen verfügen über zugängliche Attribute
print(f"Name: {student1.name}")
print(f"Major: {student1.major}")
print(f"Universität: {student1.university}")
# Klasse ist auch ein Objekt
print(type(Student)) # <class 'type'>
print(Student.__name__) # Student
print(Student.university) # Universitas IndonesiaSpezielle Methoden beginnen und enden mit doppelten Unterstrichen. Python ruft sie über Syntax und Built-ins wie +, abs(), repr() und Wahrheitstests auf. Implementiere eine solche Methode nur, wenn ihre Bedeutung für die Domäne natürlich ist.
from math import hypot
class Vector2D:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
"""Gut lesbare Darstellung für Menschen."""
return f"({self.x}, {self.y})"
def __repr__(self):
"""Eindeutige Darstellung zum Debuggen."""
return f"Vector2D(x={self.x!r}, y={self.y!r})"
def __abs__(self):
"""Den Betrag des Vektors zurückgeben."""
return hypot(self.x, self.y)
def __eq__(self, other):
"""Koordinaten mit einem anderen Vector2D vergleichen."""
if not isinstance(other, Vector2D):
return NotImplemented
return self.x == other.x and self.y == other.y
def __add__(self, other):
"""Einen neuen Vektor aus der koordinatenweisen Summe bilden."""
if not isinstance(other, Vector2D):
return NotImplemented
return Vector2D(self.x + other.x, self.y + other.y)
def __bool__(self):
"""Der Nullvektor ist false, jeder andere Vektor true."""
return bool(self.x or self.y)
first = Vector2D(3, 4)
second = Vector2D(1, -2)
print(first) # (3, 4) über __str__
print(repr(first)) # Vector2D(x=3, y=4)
print(abs(first)) # 5.0 über __abs__
print(first == Vector2D(3, 4)) # True über __eq__
combined = first + second # __add__ liefert einen neuen Vektor
print(combined) # (4, 2)
print(first) # (3, 4), unverändert
zero = Vector2D(0, 0)
print(bool(first)) # True
print(bool(zero)) # FalseWir wollen ein komplexeres Beispiel erstellen, um zu verstehen, wie OOP in realen Szenarien angewendet wird.
class Book:
def __init__(self, title, author, isbn):
self.title = title
self.author = author
self.isbn = isbn
self.is_borrowed = False
self.borrower = None
def __str__(self):
status = "Ausgeliehen" if self.is_borrowed else "Verfügbar"
return f"{self.title} von {self.author} - {status}"
class Member:
def __init__(self, name, member_id):
self.name = name
self.member_id = member_id
self.borrowed_books = []
def __str__(self):
return f"Mitglied: {self.name} (ID: {self.member_id})"
class Library:
def __init__(self, name):
self.name = name
self.books = []
self.members = []
def add_book(self, book):
"""Buch zur Bibliothek hinzufügen"""
self.books.append(book)
return f"Buch „{book.title}“ erfolgreich hinzugefügt"
def register_member(self, member):
"""Neues Mitglied registrieren"""
self.members.append(member)
return f"Mitglied {member.name} erfolgreich registriert"
def borrow_book(self, member_id, isbn):
"""Buch ausleihen"""
# Mitglied finden
member = None
for m in self.members:
if m.member_id == member_id:
member = m
break
if not member:
return "Mitglied nicht gefunden"
# Buch finden
book = None
for b in self.books:
if b.isbn == isbn and not b.is_borrowed:
book = b
break
if not book:
return "Buch nicht verfügbar"
# Ausleihe verarbeiten
book.is_borrowed = True
book.borrower = member
member.borrowed_books.append(book)
return f"{member.name} hat '{book.title}' erfolgreich ausgeliehen"
def return_book(self, member_id, isbn):
"""Buch zurückgeben"""
member = None
for m in self.members:
if m.member_id == member_id:
member = m
break
if not member:
return "Mitglied nicht gefunden"
book = None
for b in member.borrowed_books:
if b.isbn == isbn:
book = b
break
if not book:
return "Das Buch wurde nicht in der Ausleihliste gefunden"
# Rückgabe verarbeiten
book.is_borrowed = False
book.borrower = None
member.borrowed_books.remove(book)
return f"{member.name} hat erfolgreich „{book.title}“ zurückgegeben."
def get_available_books(self):
"""Liste der verfügbaren Bücher zurückgeben"""
available = [book for book in self.books if not book.is_borrowed]
return available
def get_member_books(self, member_id):
"""Von einem Mitglied ausgeliehene Bücher zurückgeben"""
for member in self.members:
if member.member_id == member_id:
return member.borrowed_books
return []
# Beispielhafte Nutzung eines Bibliothekssystems
library = Library("Zentralbibliothek")
# Bücher hinzufügen
book1 = Book("Python Programming", "John Smith", "978-1234567890")
book2 = Book("Data Science Basics", "Jane Doe", "978-0987654321")
book3 = Book("Machine Learning", "Bob Johnson", "978-1122334455")
print(library.add_book(book1))
print(library.add_book(book2))
print(library.add_book(book3))
# Mitglieder registrieren
member1 = Member("Alice Cooper", "M001")
member2 = Member("Bob Wilson", "M002")
print(library.register_member(member1))
print(library.register_member(member2))
# Bücher ausleihen
print(library.borrow_book("M001", "978-1234567890"))
print(library.borrow_book("M002", "978-0987654321"))
# Buchstatus anzeigen
print("\nListe aller Bücher:")
for book in library.books:
print(book)
print("\nVerfügbare Bücher:")
for book in library.get_available_books():
print(book)
print(f"\nVon Alice ausgeliehene Bücher: {len(library.get_member_books('M001'))} Bücher")
# Rückgabe von Büchern
print(library.return_book("M001", "978-1234567890"))Pythons Objektmodell erklärt, warum Werte, Funktionen und Klassen dieselben Sprachmechanismen durchlaufen können. Nutze objektorientierte Komposition, wenn Zustand und Verhalten eine sinnvolle Grenze bilden. Ein prozedurales oder funktionales Design bleibt besser, wenn es das Problem direkter ausdrückt.