Zum Inhalt springen
> 💻 🧠 Code 1001 > Klassen in Python, OOP und Kontextmanager: Vollständiger Leitfaden

Klassen in Python, OOP und Kontextmanager: Vollständiger Leitfaden

  • von

1. Klassen in Python

Klassen sind ein zentraler Mechanismus der OOP. Eine Klasse ist eine Vorlage, um Objekte mit Attributen (Daten) und Methoden (Funktionen) zu erstellen. Objekte, die aus einer Klasse erstellt werden, heißen Instanzen. Klassen helfen, Code zu strukturieren, die Wiederverwendbarkeit zu erhöhen und die Wartung zu erleichtern.

Aufbau einer Klasse

class ClassName:
    def __init__(self, param1, param2):
        self.param1 = param1
        self.param2 = param2

    def method(self):
        return f'{self.param1} und {self.param2}'

Wichtige Punkte:

  • __init__: Konstruktor zum Initialisieren von Objektattributen.
  • self: Referenz auf die aktuelle Instanz.
  • Attribute: werden über self definiert und sind in allen Methoden verfügbar.
  • Methoden: arbeiten mit den Daten des Objekts.

Objekte erstellen

class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year

    def description(self):
        return f'{self.year} {self.make} {self.model}'

my_car = Car('Toyota', 'Corolla', 2020)
print(my_car.description())  # Ausgabe: 2020 Toyota Corolla

Methodenarten

  1. Instanzmethoden — arbeiten auf Objekten (self).
  2. Klassenmethoden — arbeiten auf der Klasse (cls) über @classmethod.
  3. Statische Methoden — unabhängig von Instanz und Klasse (@staticmethod).

Vererbung

class Animal:
    def speak(self):
        return 'Tierlaut'

class Dog(Animal):
    def speak(self):
        return 'Wuff'

Polymorphismus

class Cat(Animal):
    def speak(self):
        return 'Miau'

cat = Cat()
print(cat.speak())  # Ausgabe: Miau
  • Dieselbe Methode funktioniert je nach Objekttyp unterschiedlich.

Kapselung

class Car:
    def __init__(self, make, model):
        self._make = make  # Geschütztes Attribut
        self._model = model

    def get_make(self):
        return self._make

    def set_make(self, make):
        self._make = make

Magische Methoden und Destruktor

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return f'Point({self.x}, {self.y})'

p = Point(3, 4)
print(p)  # Ausgabe: Point(3, 4)

ASCII-Diagramm: Vererbung und Polymorphismus

       ┌─────────┐
       │ Animal  │
       └─────────┘
       │ speak() │
       └─────────┘
            ▲
    ┌───────┴────────┐
    │                │
┌─────────┐      ┌─────────┐
│  Dog    │      │  Cat    │
└─────────┘      └─────────┘
│ speak() │      │ speak() │
└─────────┘      └─────────┘

2. Kontextmanager in Python

Kontextmanager ermöglichen automatisches Zuweisen und Freigeben von Ressourcen, auch bei Fehlern.

Verwendung von @contextmanager

from contextlib import contextmanager

@contextmanager
def my_context():
    print("Betritt den Kontext")
    try:
        yield "Ressource"
    finally:
        print("Verlässt den Kontext")

Verwendung:

with my_context() as res:
    print("Im Kontext:", res)

Erfassen von stdout/stderr und Tee

Python erlaubt das Erfassen von stdout, stderr oder beidem und die gleichzeitige Anzeige und Erfassung mit dem Tee-Muster.


3. Vollständiges Beispiel: oop_and_context.py

"""
oop_and_context.py

Beispiele für Klassen, OOP-Prinzipien und Kontextmanager in Python.
Enthält:
- Definition von Klassen, Vererbung, Polymorphismus, Kapselung
- Instanz-, Klassen- und statische Methoden
- Magische Methoden und Destruktor
- Kontextmanager mit @contextmanager
- Erfassen von stdout, stderr und kombiniert
- Tee-Muster: gleichzeitig anzeigen und erfassen
- Klassenbasierter Kontextmanager
"""

import sys
import io
from contextlib import contextmanager

# ==========================
# Teil 1: Klassen und OOP
# ==========================

class Animal:
    """Basisklasse für Tiere."""
    def speak(self):
        return 'Tierlaut'

class Dog(Animal):
    def speak(self):
        return 'Wuff'

class Cat(Animal):
    def speak(self):
        return 'Miau'

class Car:
    """Beispiel für Kapselung."""
    def __init__(self, make, model, year=None):
        self._make = make
        self._model = model
        self.year = year

    def get_make(self):
        return self._make

    def set_make(self, make):
        self._make = make

    def description(self):
        if self.year:
            return f'{self.year} {self._make} {self._model}'
        return f'{self._make} {self._model}'

class Point:
    """Klasse mit magischen Methoden."""
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return f'Point({self.x}, {self.y})'

# ==========================
# Teil 2: Kontextmanager
# ==========================

@contextmanager
def my_context():
    print("Betritt den Kontext")
    try:
        yield "Ressource"
    finally:
        print("Verlässt den Kontext")

@contextmanager
def capture_stdout():
    old_stdout = sys.stdout
    sys.stdout = buffer = io.StringIO()
    try:
        yield buffer
    finally:
        sys.stdout = old_stdout

@contextmanager
def capture_stderr():
    old_stderr = sys.stderr
    sys.stderr = buffer = io.StringIO()
    try:
        yield buffer
    finally:
        sys.stderr = old_stderr

@contextmanager
def capture_output():
    old_stdout = sys.stdout
    old_stderr = sys.stderr
    sys.stdout = sys.stderr = buffer = io.StringIO()
    try:
        yield buffer
    finally:
        sys.stdout = old_stdout
        sys.stderr = old_stderr

class Tee(io.StringIO):
    """Sichtbare Ausgabe und gleichzeitige Erfassung."""
    def __init__(self, original):
        super().__init__()
        self.original = original

    def write(self, text):
        self.original.write(text)
        super().write(text)

    def flush(self):
        self.original.flush()

@contextmanager
def capture_stdout_tee():
    old_stdout = sys.stdout
    sys.stdout = tee = Tee(old_stdout)
    try:
        yield tee
    finally:
        sys.stdout = old_stdout

# ==========================
# Teil 3: Klassenbasierter Kontextmanager
# ==========================

class OutputCapture:
    """Klassenbasierter Kontextmanager zum Erfassen von stdout."""
    def __init__(self):
        self._buffer = io.StringIO()
        self._old_stdout = None

    def __enter__(self):
        self._old_stdout = sys.stdout
        sys.stdout = self._buffer
        return self._buffer

    def __exit__(self, exc_type, exc_val, exc_tb):
        sys.stdout = self._old_stdout
        return False  # Ausnahmen weitergeben

# ==========================
# Teil 4: Demonstrationen
# ==========================

def demo_classes():
    print("\n--- Klassen-Demonstration ---")
    dog = Dog()
    cat = Cat()
    print("Hund sagt:", dog.speak())
    print("Katze sagt:", cat.speak())

    my_car = Car('Toyota', 'Corolla', 2020)
    print("Autobeschreibung:", my_car.description())
    my_car.set_make('Honda')
    print("Aktualisierte Marke:", my_car.get_make())

    point = Point(3, 4)
    print("Punkt:", point)

def demo_context_managers():
    print("\n--- Kontextmanager-Demonstration ---")
    with my_context() as res:
        print("Im Kontext:", res)

with capture_stdout() as out:
    print("stdout erfasst")
print("Buffer:", out.getvalue().strip())

with capture_stderr() as err:
    print("Geht zu stdout")
    sys.stderr.write("Fehlermeldung\n")
print("Fehler:", err.getvalue().strip())

with capture_output() as out_all:
    print("Stdout in kombinierter Erfassung")
    sys.stderr.write("Stderr in kombinierter Erfassung\n")
print("Kombinierte Ausgabe:", out_all.getvalue().strip())

with capture_stdout_tee() as tee_out:
    print("Ausgabe sichtbar UND erfasst mit Tee")
print("Tee Buffer:", tee_out.getvalue().strip())

with OutputCapture() as class_capture:
    print("Erfassung mit klassenbasiertem Kontextmanager")
print("Buffer des Klassenmanagers:", class_capture.getvalue().strip())

# ==========================
# Hauptausführung
# ==========================

if name == "main":
demo_classes()
demo_context_managers()

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert