Skip to content

Technik Blog

Programmieren | Arduino | ESP32 | MicroPython | Python | Raspberry Pi | Raspberry Pi Pico

Menu
  • Smarthome
  • Gartenautomation
  • Arduino
  • ESP32 & Co.
  • Raspberry Pi & Pico
  • Solo Mining
  • Deutsch
  • English
Menu

Python #15: Private Variablen und Methoden

Posted on 16. April 20201. Mai 2023 by Stefan Draeger

Wenn man eine Klasse in Python schreibt kann diese nicht nur Daten / Eigenschaften in Variablen speichern sondern kann auch Methoden und Eigenschaften besitzen welche von außen nicht zugreifbar sein sollen.

  • Einleitung
  • Konvention
  • definieren einer privaten Variable
    • private Methoden

Einleitung

In diesem Beitrag möchte ich dir nun zeigen wie du den Zugriff auf Eigenschaften und / oder Methoden deiner Klasse von außen verhinderst.

Für dieses Beispiel verwende ich eine einfache Klasse Auto, welche die Eigenschaften, Marke, Modell und Baujahr besitzt.

class Auto():
    def __init__(self, marke, modell, baujahr):
        self.marke = marke
        self.modell = modell
        self.baujahr = baujahr
        
    def typ(self):
        print(self.marke, self.modell, self.baujahr, sep=",")

Zusätzlich habe ich noch zwei Methoden implementiert, einmal den Konstruktor zum erstellen eines Auto Objektes sowie eine Methode zum formatierten Ausgeben der gespeicherten Daten.

Wir können uns nun wie bekannt ein oder mehrere Objekte erzeugen:

class Auto():
    def __init__(self, marke, modell, baujahr):
        self.marke = marke
        self.modell = modell
        self.baujahr = baujahr
        
    def typ(self):
        print(self.marke, self.modell, self.baujahr, sep=",")
        
auto1 = Auto("VW","Golf",2000)
auto1.typ()
        
auto2 = Auto("Audi","RS8",2018)
auto2.typ()

auto3 = Auto("BMW","3er",2010)
auto3.typ()

Wenn wir nun diesen Code ausführen dann erhalten wir folgende Ausgabe:

VW,Golf,2000
Audi,RS8,2018
BMW,3er,2010

Soweit ist das gut. 

Nun nehmen wir an wir sind ein Autohaus und wollen unseren Lagerbestand über die Klasse „Auto“ verfolgen.

Am einfachsten wäre es also nun das wir eine zusätzliche Variable / Eigenschaft „lagerbestand“ hinzufügen.

class Auto():
    def __init__(self, marke, modell, baujahr):
        self.marke = marke
        self.modell = modell
        self.baujahr = baujahr
        self.lagerbestand = 1
        
    def typ(self):
        print(self.marke, self.modell, self.baujahr, "Lagerbestand =", str(self.lagerbestand))

Ich habe hier zusätzlich den Seperator entfernt da dieser sonst zwischen „Lagerbestand =“ und dem Wert ein Komma setzen würde.

Wir könnten nun jederzeit von außen den Wert „lagerbestand“ beliebig manipulieren.

auto1 = Auto("VW","Golf",2000)
auto1.lagerbestand = 9
auto1.typ()
        
auto2 = Auto("Audi","RS8",2018)
auto2.lagerbestand = 12
auto2.typ()

auto3 = Auto("BMW","3er",2010)
auto3.lagerbestand = -1
auto3.typ()

Im letzten Fall haben wir einen Lagerbestand von -1 eingegeben, nach unser zunächst definierten Regel darf aber minimal der Wert 0 gelten.

Es gibt nur 2 Möglichkeiten dem Benutzer unserer Klasse Auto mitzuteilen das dieser die Variable / Eigenschaft „lagerbestand“ nicht selber manipulieren soll.

Konvention

Jede Programmiersprache hat Ihre Regeln wo sich die Entwickler dran halten sollten (nach Möglichkeiten), diese Regeln nennt man auch Konventionen. Eine dieser Regel ist zbsp. das Variablen und Methoden mit einem beginnenden Unterstrich nicht verwendet werden sollten.

D.h. wenn wir nun unsere Klasse Auto so umschreiben das die Variable „lagerbestand“ mit einem Unterstrich beginnt, sollte jeder Programmierer, welcher sich an die Konventionen von Python hält nicht auf diese Variable zugreifen.

class Auto():
    def __init__(self, marke, modell, baujahr):
        self.marke = marke
        self.modell = modell
        self.baujahr = baujahr
        self._lagerbestand = 1
        
    def typ(self):
        print(self.marke, self.modell, self.baujahr, "Lagerbestand =", str(self._lagerbestand))

Wir können aber trotzdem noch den Wert für den Lagerbestand manipulieren.

auto1 = Auto("VW","Golf",2000)
auto1._lagerbestand = 9
auto1.typ()
        
auto2 = Auto("Audi","RS8",2018)
auto2._lagerbestand = 12
auto2.typ()

auto3 = Auto("BMW","3er",2010)
auto3._lagerbestand = -1
auto3.typ()
VW Golf 2000 Lagerbestand = 9
Audi RS8 2018 Lagerbestand = 12
BMW 3er 2010 Lagerbestand = -1

Da sich nicht alle Programmierer an diese Regeln halten, sollten wir also sicherstellen das dieser Wert korrekt manipuliert werden kann.

Dazu schreiben wir uns zwei kleine Hilfsmethoden:

def increase_lagerbestand(self):
   self._lagerbestand = self._lagerbestand + 1
        
def decrease_lagerbestand(self):
   if self._lagerbestand >0:
      self._lagerbestand = self._lagerbestand - 1

Die Methode „increase_lagerbestand“ erhöht den Lagerbestand um 1 und die Methode „decrease_lagerbestand“ verringert den Lagerbestand um 1, aber nur wenn der Lagerbestand größer als 0 ist.

auto1 = Auto("VW","Golf",2000)
auto1.increase_lagerbestand()
auto1.increase_lagerbestand()
auto1.increase_lagerbestand()
auto1.typ()
auto1.decrease_lagerbestand()
auto1.decrease_lagerbestand()
auto1.typ()
        
auto2 = Auto("Audi","RS8",2018)
auto2.increase_lagerbestand()
auto2.decrease_lagerbestand()
auto2.increase_lagerbestand()
auto2.typ()

auto3 = Auto("BMW","3er",2010)
auto3._lagerbestand = -1
auto3.typ()
auto3.decrease_lagerbestand()
auto3.typ()

Im ersten Auto Objekt haben 3 mal den Lagerbestand um 1 erhöht, somit ist der Lagerbestand 4 (Startwert ist 1). Danach rufen wir 2 mal die Methode „decrease_lagerbestand“ auf und verringern somit den Lagerbestand um 1. Ähnlich verläuft dieses beim zweiten Auto Objekt.

Im dritten Auto Objekt jedoch greifen wir zunächst auf den Lagerbestand per Variable zu und setzen diesen auf den Wert -1 wenn wir nun den Lagerbestand mit der Methode „decrease_lagerbestand“ verringern wird dieses nicht gemacht da der Wert kleiner als 0 ist.

VW Golf 2000 Lagerbestand = 4
VW Golf 2000 Lagerbestand = 2
Audi RS8 2018 Lagerbestand = 2
BMW 3er 2010 Lagerbestand = -1
BMW 3er 2010 Lagerbestand = -1

Nun bleibt eine Frage offen: Wie können wir wirklich sicherstellen das die Eigenschaft „lagerbestand“ von außen nicht manipuliert werden kann? Und dieses wollen wir im nächsten Abschnitt durchführen.

definieren einer privaten Variable

Zunächst haben wir darauf gesetzt das der Programmierer die Regeln und / oder Konventionen von Python einhält. In diesem Abschnitt möchte ich nun aufzeigen wie einfach es ist eine private Variable / Methode zu erstellen.

Im ersten Abschnitt habe ich einen (1) Unterstrich vor die Variable „lagerbestand“ gesetzt, um nun aus dieser Variable eine private Variable zu machen benötigen wir zwei (2) Unterstriche vor der Variablen.

class Auto():
    def __init__(self, marke, modell, baujahr):
        self.marke = marke
        self.modell = modell
        self.baujahr = baujahr
        self.__lagerbestand = 1
        
    def typ(self):
        print(self.marke, self.modell, self.baujahr, "Lagerbestand =", str(self.__lagerbestand))
    
    def increase_lagerbestand(self):
        self.__lagerbestand = self.__lagerbestand + 1
        
    def decrease_lagerbestand(self):
        if self.__lagerbestand >0:
            self.__lagerbestand = self.__lagerbestand - 1

Wenn wir also versuchen die nun private Variable „__lagerbestand“  wie folgt zu manipulieren. 

auto3 = Auto("BMW","3er",2010)
auto3.__lagerbestand = -8
auto3.typ()
auto3.decrease_lagerbestand()
auto3.typ()

Dann sieht die Ausgabe wie folgt aus:

BMW 3er 2010 Lagerbestand = 1
BMW 3er 2010 Lagerbestand = 0
-8

Aber warum?

Wir haben in diesem Fall unserem dritten Auto Objekt eine neue Eigenschaft „__lagerbestand“ hinzugefügt welche die eigentliche Variable im originalen Auto Objekt nicht kennt (diese ist ja privat). Also können wir diese auch manipulieren und ausgeben. Die beiden Methoden „increase_lagerbestand“ und „decrease_lagerbestand“ arbeiten jedoch noch mit der originalen internen Variable.

Wenn wir also stattdessen folgendes schreiben würden:

class Auto():
    def __init__(self, marke, modell, baujahr):
        self.marke = marke
        self.modell = modell
        self.baujahr = baujahr
        self.__lagerbestand = 1
        
    def typ(self):
        print(self.marke, self.modell, self.baujahr, "Lagerbestand =", str(self.__lagerbestand))
    
    def increase_lagerbestand(self):
        self.__lagerbestand = self.__lagerbestand + 1
        
    def decrease_lagerbestand(self):
        if self.__lagerbestand >0:
            self.__lagerbestand = self.__lagerbestand - 1
        
auto3 = Auto("BMW","3er",2010)
auto3.typ()
auto3.decrease_lagerbestand()
auto3.typ()

print(auto3.__lagerbestand)

So erhalten wir eine Fehlermeldung dass, die Variable „__lagerbestand“ unbekannt ist.

BMW 3er 2010 Lagerbestand = 1
BMW 3er 2010 Lagerbestand = 0
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-34-f6a00e1ea387> in <module>()
     21 auto3.typ()
     22 
---> 23 print(auto3.__lagerbestand)

AttributeError: 'Auto' object has no attribute '__lagerbestand'

private Methoden

Was mit einer Variablen funktioniert kann auch genauso mit einer Methode gemacht werden. D.h. um eine Methode privat zu machen setzen wir zwei Unterstriche vor diese Methode.

Nehmen wir an wir würden einen Nachlass für den Verkauf eines Autos berechnen wollen, diese Berechnung soll natürlich geheim bleiben.

class Auto():
    def __init__(self, marke, modell, baujahr, preis):
        self.marke = marke
        self.modell = modell
        self.baujahr = baujahr
        self.preis = preis
        self.__nachlassPercent = 5
        self.__lagerbestand = 1
        
        
    def typ(self):
        print(self.marke, self.modell, self.baujahr, self.preis, "€", "Lagerbestand =", str(self.__lagerbestand))   

    def increase_lagerbestand(self):
        self.__lagerbestand = self.__lagerbestand + 1
        
    def decrease_lagerbestand(self):
        if self.__lagerbestand >0:
            self.__lagerbestand = self.__lagerbestand - 1
            
    def verkaufe(self):
        if self.__lagerbestand > 0:
            self.decrease_lagerbestand()
            print("Verkaufspreis: "+str(self.preis - self.calc_nachlass())+"€")
            
    def calc_nachlass(self):
        return (self.preis / 100) * self.__nachlassPercent

Wir verwenden in der Methode „calc_nachlass“ eine einfache Prozentrechnung wo wir z.Zt. den definierten Prozentwert von 5% vom Verkaufspreis abziehen.

Wir könnten also nun auf dem Auto Objekt die Methode „calc_nachlass“ ausführen, das wollen wir verhindern denn diese Methode soll nur intern verwendet werden. Wir setzen also nun zwei Unterstriche davor und somit können wir diese Methode nicht mehr von außen zugreifen.

def __calc_nachlass(self):
   return (self.preis / 100) * self.__nachlassPercent
auto3 = Auto("BMW","3er",2010, 9600)
auto3.typ()
auto3.verkaufe()
auto3.calc_nachlass()
BMW 3er 2010 9600 € Lagerbestand = 1
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-58-5797a46d3cf6> in <module>()
     32 auto3 = Auto("BMW","3er",2010, 9600)
     33 auto3.typ()
---> 34 auto3.verkaufe()
     35 auto3.calc_nachlass()
     36 

<ipython-input-58-5797a46d3cf6> in verkaufe(self)
     22         if self.__lagerbestand > 0:
     23             self.decrease_lagerbestand()
---> 24             print("Verkaufspreis: "+str(self.preis - self.calc_nachlass())+"€")
     25 
     26     def __calc_nachlass(self):

AttributeError: 'Auto' object has no attribute 'calc_nachlass'

Um jetzt jedoch trotzdem den Nachlass zu manipulieren schreiben wir uns eine kleine Setter Methode und können so trotzdem von außen den Wert ändern.

def set_nachlassPercent(self, perc):
   self.__nachlassPercent = perc
auto3 = Auto("BMW","3er",2010, 9600)
auto3.typ()
auto3.set_nachlassPercent(23)
auto3.verkaufe()
BMW 3er 2010 9600 € Lagerbestand = 1
Verkaufspreis: 7392.0€

Schreibe einen Kommentar Antworten abbrechen

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

Fragen oder Feedback?

Du hast eine Idee, brauchst Hilfe oder möchtest Feedback loswerden?
Support-Ticket erstellen

Newsletter abonnieren

Bleib auf dem Laufenden: Erhalte regelmäßig Updates zu neuen Projekten, Tutorials und Tipps rund um Arduino, ESP32 und mehr – direkt in dein Postfach.

Jetzt Newsletter abonnieren

Unterstütze meinen Blog

Wenn dir meine Inhalte gefallen, freue ich mich über deine Unterstützung auf Tipeee.
So hilfst du mit, den Blog am Leben zu halten und neue Beiträge zu ermöglichen.

draeger-it.blog auf Tipeee unterstützen

Vielen Dank für deinen Support!
– Stefan Draeger

Kategorien

Tools

  • Unix-Zeitstempel-Rechner
  • ASCII Tabelle
  • Spannung, Strom, Widerstand und Leistung berechnen
  • Widerstandsrechner
  • 8×8 LED Matrix Tool
  • 8×16 LED Matrix Modul von Keyestudio
  • 16×16 LED Matrix – Generator

Links

Blogverzeichnis Bloggerei.de TopBlogs.de das Original - Blogverzeichnis | Blog Top Liste Blogverzeichnis trusted-blogs.com

Stefan Draeger
Königsberger Str. 13
38364 Schöningen

Tel.: 01778501273
E-Mail: info@draeger-it.blog

Folge mir auf

  • Impressum
  • Datenschutzerklärung
  • Disclaimer
  • Cookie-Richtlinie (EU)
©2025 Technik Blog | Built using WordPress and Responsive Blogily theme by Superb
Cookie-Zustimmung verwalten
Wir verwenden Technologien wie Cookies, um Geräteinformationen zu speichern und/oder darauf zuzugreifen. Wir tun dies, um das Surferlebnis zu verbessern und um personalisierte Werbung anzuzeigen. Wenn Sie diesen Technologien zustimmen, können wir Daten wie das Surfverhalten oder eindeutige IDs auf dieser Website verarbeiten. Wenn Sie Ihre Zustimmung nicht erteilen oder zurückziehen, können bestimmte Funktionen beeinträchtigt werden.
Funktional Immer aktiv
Die technische Speicherung oder der Zugang ist unbedingt erforderlich für den rechtmäßigen Zweck, die Nutzung eines bestimmten Dienstes zu ermöglichen, der vom Teilnehmer oder Nutzer ausdrücklich gewünscht wird, oder für den alleinigen Zweck, die Übertragung einer Nachricht über ein elektronisches Kommunikationsnetz durchzuführen.
Vorlieben
Die technische Speicherung oder der Zugriff ist für den rechtmäßigen Zweck der Speicherung von Präferenzen erforderlich, die nicht vom Abonnenten oder Benutzer angefordert wurden.
Statistiken
Die technische Speicherung oder der Zugriff, der ausschließlich zu statistischen Zwecken erfolgt. Die technische Speicherung oder der Zugriff, der ausschließlich zu anonymen statistischen Zwecken verwendet wird. Ohne eine Vorladung, die freiwillige Zustimmung deines Internetdienstanbieters oder zusätzliche Aufzeichnungen von Dritten können die zu diesem Zweck gespeicherten oder abgerufenen Informationen allein in der Regel nicht dazu verwendet werden, dich zu identifizieren.
Marketing
Die technische Speicherung oder der Zugriff ist erforderlich, um Nutzerprofile zu erstellen, um Werbung zu versenden oder um den Nutzer auf einer Website oder über mehrere Websites hinweg zu ähnlichen Marketingzwecken zu verfolgen.
Optionen verwalten Dienste verwalten Verwalten von {vendor_count}-Lieferanten Lese mehr über diese Zwecke
Einstellungen anzeigen
{title} {title} {title}