Seite 1 von 1

Zugriff auf Basisklasse

Verfasst: Donnerstag 4. Mai 2017, 08:00
von Karsten Böhme
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

Re: Zugriff auf Basisklasse

Verfasst: Donnerstag 4. Mai 2017, 08:13
von __deets__
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.

Re: Zugriff auf Basisklasse

Verfasst: Donnerstag 4. Mai 2017, 08:18
von sebastian0202
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

Re: Zugriff auf Basisklasse

Verfasst: Donnerstag 4. Mai 2017, 09:19
von Karsten Böhme
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

Re: Zugriff auf Basisklasse

Verfasst: Donnerstag 4. Mai 2017, 09:32
von 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.)

Re: Zugriff auf Basisklasse

Verfasst: Donnerstag 4. Mai 2017, 09:34
von Sirius3
@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.

Re: Zugriff auf Basisklasse

Verfasst: Donnerstag 4. Mai 2017, 09:51
von __deets__
@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.

Re: Zugriff auf Basisklasse

Verfasst: Donnerstag 4. Mai 2017, 14:49
von Zizibee
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?

Re: Zugriff auf Basisklasse

Verfasst: Donnerstag 4. Mai 2017, 15:05
von 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)

Re: Zugriff auf Basisklasse

Verfasst: Donnerstag 4. Mai 2017, 16:57
von Karsten Böhme
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 !

Re: Zugriff auf Basisklasse

Verfasst: Donnerstag 4. Mai 2017, 17:35
von __deets__
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.

Re: Zugriff auf Basisklasse

Verfasst: Donnerstag 4. Mai 2017, 18:22
von Karsten Böhme
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.

Re: Zugriff auf Basisklasse

Verfasst: Donnerstag 4. Mai 2017, 22:39
von __deets__
Das kann ja sein. Aber es hat nichts mit der Privatheit zu tun.

Re: Zugriff auf Basisklasse

Verfasst: Freitag 5. Mai 2017, 08:46
von Karsten Böhme
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.