Menu
Coddy logo textTech

Private Attribute

Teil des Abschnitts Object Oriented Programming der Python-Journey von Coddy — Lektion 15 von 64.

Private Attribute verwenden Unterstriche, um anzuzeigen, dass auf bestimmte Daten nicht direkt von außerhalb der class zugegriffen werden sollte.

Warum benötigen wir private Attribute? Stellen Sie sich vor, Sie haben ein Bankkonto. Sie möchten nicht, dass jemand Ihren Kontostand direkt ändert – man sollte offizielle Wege nutzen (deposit/withdraw Methoden), damit die Bank die Transaktion validieren, auf Betrug prüfen, Aufzeichnungen führen kann usw. Private Attribute funktionieren auf die gleiche Weise – sie schützen Ihre Daten davor, fehlerhaft geändert zu werden.

Hier ist ein Beispiel mit einem einfachen Unterstrich (Konvention für den „internen Gebrauch“):

class Person:
    def __init__(self, name, age):
        self._name = name    # "protected" - interner Gebrauch
        self._age = age      # "protected" - interner Gebrauch

Attribute mit einfachem Unterstrich können weiterhin aufgerufen werden, aber es ist ein Signal, dies nicht zu tun:

person = Person("Alice", 30)
print(person._name)  # Funktioniert, wird aber nicht empfohlen

Verwenden Sie doppelte Unterstriche für einen stärkeren Schutz der Privatsphäre (Name Mangling):

class Person:
    def __init__(self, name, age):
        self.__name = name   # "privat" - unterliegt dem Name Mangling
        self.__age = age     # "privat" - unterliegt dem Name Mangling
    
    def get_name(self):
        return self.__name
    
    def set_age(self, age):
        if age >= 0:
            self.__age = age
        else:
            print("Age must be positive!")

Warum Getter- und Setter-Methoden verwenden? Sie sind wie Torwächter. Anstatt jedem zu erlauben, __age direkt zu ändern (was zu negativen Altern oder anderen ungültigen Daten führen könnte), zwingen wir sie, set_age() zu verwenden, das die Eingabe zuerst validiert. Dies verhindert Fehler und gewährleistet die Datenintegrität.

Der „zusätzliche Code“ hat einen Zweck:

  • get_name() - Kontrollierter Zugriff zum Lesen des Namens
  • set_age(age) - Validiert das Alter, bevor Änderungen zugelassen werden (keine negativen Alter!)
  • Ohne diese Methoden könnte jemand age = -100 setzen und Ihr Programm zum Absturz bringen

Verwenden Sie die Accessor-Methoden, um mit privaten Attributen zu interagieren:

person = Person("Bob", 25)
print(person.get_name())  # Bob

person.set_age(30)        # Gültig: Alter wird 30
person.set_age(-5)        # Ungültig: Das Alter muss positiv sein! (Alter bleibt 30)

Erkennen Sie den Vorteil? Die Methode set_age() verhindert ungültige Daten. Ohne sie könnten Sie versehentlich eine Person mit dem Alter -5 erstellen, was keinen Sinn ergibt!

Attribute mit doppeltem Unterstrich unterliegen dem "Name Mangling", können aber dennoch aufgerufen werden:

person = Person("Charlie", 35)
# Das funktioniert nicht:
# print(person.__name)  # AttributeError

# Aber das funktioniert (nicht empfohlen):
print(person._Person__name)  # Charlie

Praxisbeispiel – Warum der ganze Code?

class BankAccount:
    def __init__(self, balance):
        self.__balance = balance  # Privat: kann nicht direkt geändert werden
    
    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            return True
        return False
    
    def get_balance(self):
        return self.__balance

# Ohne private Attribute:
# account.__balance = -1000000  # Katastrophe! Negativer Kontostand erlaubt

# Mit privaten Attributen:
account = BankAccount(100)
account.deposit(50)           # Sicher: validiert
print(account.get_balance())  # 150

Der „zusätzliche Code“ (Methoden) schützt Ihre Daten vor ungültigen Änderungen. Es ist so, als hätte man Sicherheitspersonal, anstatt seine Wertsachen ungeschützt zu lassen.

Ausgabe:

Alice
Bob
Age must be positive!
Charlie
150

Ein einzelner Unterstrich _attribute bedeutet laut Konvention „nur zur internen Verwendung“. Ein doppelter Unterstrich __attribute löst Name Mangling für einen stärkeren Schutz der Privatsphäre aus. Verwenden Sie Getter/Setter-Methoden (Accessor-Methoden), um ordnungsgemäß mit privaten Daten zu interagieren und Validierungen hinzuzufügen. Der „zusätzliche Code“ verhindert Fehler, indem er sicherstellt, dass die Daten immer gültig sind.

challenge icon

Aufgabe

Einfach

Vervollständigen Sie die Klasse User in user.py mit privater Passwort-Funktionalität und verwenden Sie diese dann in driver.py. Folgen Sie den TODO-Kommentaren, um Methoden zur Passwortüberprüfung und -änderung zu implementieren.

Spickzettel

Private Attribute verwenden Unterstriche, um anzuzeigen, dass auf Daten nicht direkt von außerhalb der Klasse zugegriffen werden sollte.

Einfacher Unterstrich (_attribute) – Konvention für den „internen Gebrauch“:

class Person:
    def __init__(self, name, age):
        self._name = name    # „protected“ – interner Gebrauch
        self._age = age      # „protected“ – interner Gebrauch

Doppelter Unterstrich (__attribute) – löst Name Mangling für stärkeren Datenschutz aus:

class Person:
    def __init__(self, name, age):
        self.__name = name   # „private“ – Name wird gemangled
        self.__age = age     # „private“ – Name wird gemangled
    
    def get_name(self):
        return self.__name
    
    def set_age(self, age):
        if age >= 0:
            self.__age = age
        else:
            print("Age must be positive!")

Verwenden Sie Zugriffsmethoden, um mit privaten Attributen zu interagieren:

person = Person("Bob", 25)
print(person.get_name())  # Bob
person.set_age(30)
person.set_age(-5)        # Age must be positive!

Attribute mit doppeltem Unterstrich unterliegen dem Name Mangling, können aber dennoch aufgerufen werden (nicht empfohlen):

# Dies funktioniert nicht:
# print(person.__name)  # AttributeError

# Aber dies funktioniert (nicht empfohlen):
print(person._Person__name)  # Charlie

Probier es selbst

# TODO: Importiere die User-Klasse aus dem user-Modul

# TODO: Testfall von der Eingabe abrufen
test_case = input()

if test_case == "constructor_test":
    # TODO: Erstelle ein User-Objekt mit dem initialen Passwort "secure123"
    user = User("secure123")
    print("User created successfully")
    print("Initial password set")

elif test_case == "correct_password_test":
    # TODO: Erstelle ein User-Objekt mit dem initialen Passwort "secure123"
    user = User("secure123")
    # TODO: Teste die check_password-Methode mit dem korrekten Passwort
    #       Gib "Password check successful!" aus, wenn sie True zurückgibt
    #       Gib "Password check failed!" aus, wenn sie False zurückgibt
    result = user.check_password("secure123")
    if result:
        print("Password check successful!")
    else:
        print("Password check failed!")

elif test_case == "incorrect_password_test":
    # TODO: Erstelle ein User-Objekt mit dem initialen Passwort "secure123"
    user = User("secure123")
    # TODO: Teste die check_password-Methode mit dem falschen Passwort "wrong"
    #       Gib "Incorrect password rejected!" aus, wenn sie False zurückgibt
    #       Gib "Security issue: incorrect password accepted!" aus, wenn sie True zurückgibt
    result = user.check_password("wrong")
    if not result:
        print("Incorrect password rejected!")
    else:
        print("Security issue: incorrect password accepted!")

elif test_case == "change_password_test":
    # TODO: Erstelle ein User-Objekt mit dem initialen Passwort "secure123"
    user = User("secure123")
    # TODO: Teste die Passwortänderung von "secure123" zu "newpass456"
    #       Gib "Password changed successfully!" aus, wenn sie True zurückgibt
    #       Gib "Password change failed!" aus, wenn sie False zurückgibt
    result = user.change_password("secure123", "newpass456")
    if result:
        print("Password changed successfully!")
    else:
        print("Password change failed!")
    
    # TODO: Überprüfe, ob das neue Passwort funktioniert, indem "newpass456" geprüft wird
    #       Gib "New password works!" aus, wenn sie True zurückgibt
    #       Gib "New password doesn't work!" aus, wenn sie False zurückgibt
    if user.check_password("newpass456"):
        print("New password works!")
    else:
        print("New password doesn't work!")

elif test_case == "change_password_wrong_old_test":
    # TODO: Erstelle ein User-Objekt mit dem initialen Passwort "secure123"
    user = User("secure123")
    # TODO: Versuche das Passwort mit einem falschen alten Passwort zu ändern
    #       Gib "Security working: incorrect old password rejected!" aus, wenn sie False zurückgibt
    #       Gib "Security issue: password changed with wrong old password!" aus, wenn sie True zurückgibt
    result = user.change_password("wrong", "hackerpw")
    if not result:
        print("Security working: incorrect old password rejected!")
    else:
        print("Security issue: password changed with wrong old password!")

elif test_case == "comprehensive_test":
    # TODO: Erstelle ein User-Objekt mit dem initialen Passwort "secure123"
    user = User("secure123")
    print("User created with initial password")
    
    # TODO: Teste die check_password-Methode mit dem korrekten Passwort
    if user.check_password("secure123"):
        print("Initial password verification successful")
    
    # TODO: Teste die check_password-Methode mit einem falschen Passwort
    if not user.check_password("wrongpass"):
        print("Incorrect password properly rejected")
    
    # TODO: Teste die Passwortänderung von "secure123" zu "newpass456"
    if user.change_password("secure123", "newpass456"):
        print("Password successfully changed")
    
    # TODO: Überprüfe, ob das alte Passwort nicht mehr funktioniert
    if not user.check_password("secure123"):
        print("Old password no longer works")
    
    # TODO: Überprüfe, ob das neue Passwort funktioniert
    if user.check_password("newpass456"):
        print("New password works correctly")
    
    # TODO: Versuche das Passwort mit einem falschen alten Passwort zu ändern
    if not user.change_password("wrongold", "hackerpw"):
        print("Security maintained: wrong old password rejected")
    
    # TODO: Überprüfe, ob das Passwort nach einem fehlgeschlagenen Änderungsversuch immer noch sicher ist
    if user.check_password("newpass456"):
        print("Password remains secure after failed change attempt")

else:
    print("Unknown test case")
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Object Oriented Programming