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 GebrauchAttribute 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 empfohlenVerwenden 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 Namensset_age(age)- Validiert das Alter, bevor Änderungen zugelassen werden (keine negativen Alter!)- Ohne diese Methoden könnte jemand
age = -100setzen 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) # CharliePraxisbeispiel – 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()) # 150Der „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
150Ein 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.
Aufgabe
EinfachVervollstä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 GebrauchDoppelter 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) # CharlieProbier 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")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
1Grundlagen der OOP
Externe DateienEinführung in die OOPKlassen vs. ObjekteDer self-ParameterMethodenAttributeKonstruktor-Methode (__init__)Zusammenfassung – Einfacher Taschenrechner4Vererbung
Grundlagen der VererbungDie super()-FunktionMethoden überschreibenMehrfachvererbungMethod Resolution OrderZusammenfassung - Mitarbeiter-Hierarchie7Spezielle Methoden
Einführung in Magic MethodsOperator-ÜberladungMagic Methods für ContainerRückblick - Eigene Liste10Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster13Abschlussherausforderungen
E-Learning-PlattformBanksystemSpielcharakter-EntwicklungFahrzeugvermietung2Dekoratoren
Einführung in DekoratorenProperty-DekoratorStatischer Methoden-DekoratorKlassenmethoden-Dekorator5Polymorphismus
Methoden-Überschreiben vertieftDuck TypingAbstrakte Klassen und MethodenInterface-DesignZusammenfassung – Formen-Rechner8Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungMixinsStatische und KlassenmethodenKlassendekoratorenContext Manager3Klasseneigenschaften
Instanz- vs. KlassenvariablenProperty-DekoratorenPrivate AttributeZusammenfassung – Bankkonto-Manager6Kapselung
Public, Protected, Private MemberZugriffsmodifikatorenInformation HidingProperty-Decorators für FortgeschritteneZusammenfassung - Studentenverwaltungssystem12Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen