Zugriff auf Basisklasse

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Karsten Böhme
User
Beiträge: 86
Registriert: Sonntag 23. Dezember 2012, 07:54

Hallo miteinander,

ich möchte aus einer Basisklasse den Wert eines privaten Attributes auslesen und komme da nicht so recht weiter. Das Ganze sieht ungefähr so aus :

Code: Alles auswählen

class A:
	def __init__(self):
		self.__x = 1
		
class B(A):
	def f(self):
		x = super().__x
Geht natürlich nicht ! Was habe ich hier für Möglichkeiten ?

Viele Dank im voraus !

Karsten
Zuletzt geändert von Anonymous am Donnerstag 4. Mai 2017, 09:44, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Es so nicht zu machen. Dieser Mechanismus ist genau NICHT dafür gemacht private Attribute zu spielen, sondern soll genau so funktionieren wie du es erlebst: potentielle namenskonflikte in Ableitungshierarchien lösen.

Nimm einfach der Konvention entsprechend nur EINEN unterstrich, und alles ist tutti.
sebastian0202
User
Beiträge: 168
Registriert: Montag 9. Mai 2016, 09:14
Wohnort: Berlin

Hallo,



ganz einfach:

Code: Alles auswählen

class A:
    def __init__(self):
        self.x = 1
      
class B(A):
    def f(self):
        x = self.x
Schau dir mal Punkt 9.6 an:
https://docs.python.org/2/tutorial/clas ... ut-private
Karsten Böhme
User
Beiträge: 86
Registriert: Sonntag 23. Dezember 2012, 07:54

Vielen Dank für die schnellen Antworten !

@__deets__ : Hatte ich auch schon probiert, funktioniert weder mit einem Unterstrich noch ohne Unterstrich.

@sebastian22 : Dein Tipp war der Richtige ! Allerdings auch nur mit einem Unterstrich.

Was mir noch nicht ganz einleuchtet, ein privates Attribut soll doch von den Nutzern einer Instanz nicht gesehen werden. Eine erbende Klasse sollte doch aber die Möglichkeit haben. Ist ja eigentlich auch nötig (z.B. in meinem Fall).

Gruß

Karsten
BlackJack

@Karsten Böhme: Es gibt in Python kein ``private``, also keinen Zugriffsschutz wie in Java & Co.

Selbst wenn es das gäbe, hättest Du das gleiche Problem denn ``private`` bedeutet wirklich nur in *der* Klasse zugreifbar. Nicht in Unterklassen.

Edit: Das hier geht auch in Java nicht:
[codebox=java5 file=Unbenannt.java]public class A {
private int x;

public A(int x) {
this.x = x;
}
}

public class B extends A {

public B(int x) {
super(x);
}

int method() {
return x * 42; // Error: `x` is declared private in `A`.
}
}[/code]

Da müsste man eine Gettermethode in `A` hinzufügen:
[codebox=java5 file=Unbenannt.java]public class A {
private int x;

public A(int x) {
this.x = x;
}

public int getX() {
return x;
}
}

public class B extends A {

public B(int x) {
super(x);
}

int method() {
return getX() * 42;
}
}[/code]
(Bitte nicht in Python nachmachen.)
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Karsten Böhme: es gibt keine privaten Attribute. Es gibt öffentliche Attribute (ohne Unterstrich), interne Attribute (mit einem Unterstrich) und Attribute, die nicht aus vererbten Klassen angesprochen werden sollen (zwei Unterstriche). Du hast die letzte Variante gewählt, obwohl Du auf ein vererbtes Attribut zugreifen wolltest, was dann, wie von Python vorgesehen, nicht funktioniert hat.
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

@Karsten: sehr wohl geht das:

Code: Alles auswählen

class A:
    def __init__(self):
        self._x = 1

class B(A):
    def f(self):
        x = self._x
        return x


def main():
    b = B()
    print(b.f())


if __name__ == '__main__':
    main()
Du musst dir allerdings auch noch das super sparen, die Attribute einer Python-Instanz sind in einem einzigen flachen Namensraum abgelegt.
Zizibee
User
Beiträge: 229
Registriert: Donnerstag 12. April 2007, 08:36

Auch wenn die Frage etwas am Thema vorbei führt stelle ich sie einfach mal, weil sie mir beim Betrachten des Codes gekommen ist und ich im Netz keine passende Antwort gefunden habe.
In diesem Minimalbeispiel ist _x eine Konstante, da sie nie geändert wird. Würde man Konstanten wirklich in der __init__ jedem Objekt zuweisen, oder würde sie global für alle Objekte der Klasse abgelegt werden (können)?

So etwas wie

Code: Alles auswählen

class Test:
    KONSTANTE = 5
    
    def __init__(self):
        pass
 
    def get(self):
      global KONSTANTE
      print(KONSTANTE)
funktioniert ja nicht.

Oder passt da schon mein Grundgedanke nicht?
BlackJack

@Zizibee: Konstante auf Klassen sind wie (ungebundene) Methoden auf Klassen: Attribute der Klasse. Also entweder über die Klasse oder in Exemplaren zusätzlich über `self` erreichbar:

Code: Alles auswählen

class Test(object):
    
    KONSTANTE = 5
    
    def method(self):
        print(Test.KONSTANTE)
        print(self.KONSTANTE)
Karsten Böhme
User
Beiträge: 86
Registriert: Sonntag 23. Dezember 2012, 07:54

Vielen Dank für die vielen Hinweise !

@__deets__ : Ja, es geht !

Habe jetzt ne 'raed only' Property eingefügt. Ist mir lieber als ein Unterstrich. Liegt wohl an meiner C#-Vergangenheit ...

Vielen Dank und bis zum nächsten mal !
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das sind doch zwei voellig orthogonale Konzepte. Das eine bezieht sich darauf welches Publikum deine Eigenschaft hat. Die Allgemeinheit, oder nur "nahe Verwandte". Das andere ist eine semantische Eigenschaft, reine Lesbarkeit.
Karsten Böhme
User
Beiträge: 86
Registriert: Sonntag 23. Dezember 2012, 07:54

Da die Basisklasse auch allein eingesetzt werden kann (Event-System) und der betreffende Wert nur über den Konstruktor einmalig zugewiesen wird, denke ich, eine 'read only'-Property ist schon angebracht.
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das kann ja sein. Aber es hat nichts mit der Privatheit zu tun.
Karsten Böhme
User
Beiträge: 86
Registriert: Sonntag 23. Dezember 2012, 07:54

Nein, da hast Du recht. Das meinte ich jetzt auch nicht. Die Property soll nur vor unerlaubten Schreibzugriff schützen, den Wert benötige ich nun mal in der erbenden Klasse.
Antworten