self erklären

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
mzh
User
Beiträge: 295
Registriert: Dienstag 3. März 2009, 15:27
Wohnort: ZH

Hallo zusammen

Ich versuche einem Kollegen 'self' zu erklären. Dazu habe ich folgendes Programm geschrieben, dass den Witz dahinter m.E. illustriert.
Sind meine Kommentare im Programm zutreffend?

Code: Alles auswählen

#!/usr/bin/env python

class Machine:
    
    #Class Variable counts how many machines
    #have been created.
    #The value is the same for all objects
    #of this class.
    counter = 0 
    
    def __init__(self):
    
        #This is a short hand notation for
        #Machine.counter = Machine.counter + 1
        #Notice: no 'self'.
        Machine.counter += 1
    
        #This variable is an instance variable.
        #It is different for every object of
        #the class.
        self.id = Machine.counter
    
    def getID(self):
        #You need 'self' here to adress the
        #variable of the particular object
        #calling this method.
        return self.id
    
    def getCounter(self):
        #No 'self' here. You call the
        #variable of the class.
        return Machine.counter
    
if __name__ == '__main__':
    machine1 = Machine()
    machine2 = Machine()
    machine3 = Machine()
    
    #The value is different for all objects.
    print 'machine1.getID()', machine1.getID()
    print 'machine2.getID()', machine2.getID()
    print 'machine3.getID()', machine3.getID()
    
    print
    print
    
    #The value is the same for all objects.
    print 'machine1.getCounter()', machine1.getCounter()
    print 'machine2.getCounter()', machine2.getCounter()
    print 'machine3.getCounter()', machine3.getCounter()
[url=http://www.proandkon.com]proandkon.com[/url]
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Die get Methoden sind überflüssig, die Kommentare stimmen so.
mzh
User
Beiträge: 295
Registriert: Dienstag 3. März 2009, 15:27
Wohnort: ZH

@DasIch: du meinst, man ruft die Variable direkt auf: print Machine.counter ? Danke für den Hinweis.
[url=http://www.proandkon.com]proandkon.com[/url]
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

mzh hat geschrieben:@DasIch: du meinst, man ruft die Variable direkt auf: print Machine.counter ? Danke für den Hinweis.
Das gleiche gilt für

Code: Alles auswählen

print machine1.id
Getter und Setter stammen aus Bondage-Sprachen wie Java und sollten nur dann verwendet werden, wenn sie wirklich einen Mehrwert bieten.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

/me hat geschrieben:Getter und Setter stammen aus Bondage-Sprachen wie Java und sollten nur dann verwendet werden, wenn sie wirklich einen Mehrwert bieten.
So abwertend sollte man das nicht formulieren.

Dass man getter und setter in Python nicht braucht, liegt einzig und allein daran, dass es Properties gibt, die von außen nicht von einem normalen Attributzugriff zu unterscheiden sind. Oder anders aus gedrückt, man kann Instanzvariablen durch Properties ersetzen ohne die Schnittstelle nach außen zu ändern. Und das ist ein ziemlichen Alleinstellungsmerkmal von Python. Das geht auch in vielen nicht-„bondage“-Sprachen nicht.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Darii hat geschrieben:
/me hat geschrieben:Und das ist ein ziemlichen Alleinstellungsmerkmal von Python.
Naja, wenn ich so überlege fällt mir recht bald C# und Scala ein. Also so selten ist das ja nicht.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Leonidas hat geschrieben:
Darii hat geschrieben:
/me hat geschrieben:Und das ist ein ziemlichen Alleinstellungsmerkmal von Python.
Naja, wenn ich so überlege fällt mir recht bald C# und Scala ein. Also so selten ist das ja nicht.
Die Properties von C# werden vom Compiler in Methodenaufrufe umgeschrieben, d.h. das ganze funktioniert nur, so lange du den Quellcode zur Verfügung hast und du das neu kompilieren kannst. Kompatibilität auf Bytecodeebene ist aber nicht gegeben. Anders als bei Python. Bei Scala wird das nicht anders laufen.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Darii hat geschrieben:
/me hat geschrieben:...Bondage-Sprachen...
So abwertend sollte man das nicht formulieren.
Mir gefällt's :mrgreen:
Darii hat geschrieben:Dass man getter und setter in Python nicht braucht, liegt einzig und allein daran, dass es Properties gibt, die von außen nicht von einem normalen Attributzugriff zu unterscheiden sind. Oder anders aus gedrückt, man kann Instanzvariablen durch Properties ersetzen ohne die Schnittstelle nach außen zu ändern. Und das ist ein ziemlichen Alleinstellungsmerkmal von Python.
Bei Eiffel gab's das AFAIK zuerst.

Gruß,
Mick.
In specifications, Murphy's Law supersedes Ohm's.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

pillmuncher hat geschrieben:Bei Eiffel gab's das AFAIK zuerst.
Nein, wenn ich das richtig verstehe, funktioniert das da genauso wie in C#. Die Attributzugriffe werden vom Compiler in Methodenaufrufe umgeschrieben. Allerdings hat man da wohl das Java-Problem nicht, da man überhaupt nicht die Möglichkeit hat, direkt auf ein Attribut zuzugreifen.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Es gibt Sprachen, in den gibt es keine von außen sichtbaren Variablen wie z.B. Smalltalk. Dort hat man immer Methoden, die einfach wie Properties aussehen. In Smalltalk-78 konnte man `foo bar = foo bar + 1` schreiben, was dann das "Property" `bar` des Objekts `foo` erhört. Ab Smalltalk-80 ist das zu `foo bar: foo bar + 1` geworden, weil man den komischen Methodennamen `bar =` (mit optionalem Leerzeichen) nicht haben wollte. Was sich hinter `bar` und `bar:` verbirgt und ob das einfach nur Getter und Setter sind oder komplexe Berechnungen, sieht man nicht und kann man ohne Rekompilation des restlichen Programms ändern. Und das war mehr als 10 Jahre vor Python.

Stefan
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Darum gings ja auch gar nicht. Wenn ich sowieso nur Methoden zur Verfügung habe, kann man sie natürlich trivialer Weise, ohne den restlichen Teil des Programm zu ändern, durch Methoden mit derselben Signatur ersetzen kann. Das geht sogar bei C++(wenn da nicht gerade irgendwas geinlined wurde).

Mir ging es darum, dass Properties in Python dieselbe (öffentliche) Schnittstelle nach außen haben, wie normale Attribute. Und das ist afaik bei keiner anderen Sprache so. Bei Smalltalk gibt es keine öffentliche Schnittstelle zu Instanzvariablen, also stellt sie dich Frage gar nicht erst.

Wobei man natürlich argumentieren könnte, dass Python auch keinen direkten Zugriff auf Instanzvariablen bietet, dann läuft es im Endeffekt auf selbe hinaus, bloß dass Python mit noch mehr CPU-Zyklen die Wohnung heizt, als Smalltalk.
lunar

@Darii: Scala erzeugt meines Wissens implizit Zugriffsmethoden für öffentliche Attribute. Um die Zugriffsmethoden zu erweitern, kann man also nachträglich das Attribut umbenennen und die Zugriffsmethoden manuell implementieren, ohne dass sich die öffentliche Schnittstelle (sowohl binär als auch im Quelltext) dadurch ändert. Bei Scala sind also faktisch alle Attribute Eigenschaften.

Allerdings würde ich nicht sagen, dass Eigenschaften in Python dieselbe öffentliche Schnittstelle wie Eigenschaften haben. Schließlich unterscheiden sich Eigenschaften als Deskriptoren doch deutlich von normalen Attributen. Nur ist das eben vollkommen egal, weil Zugriffe immer erst zur Laufzeit aufgelöst werden.
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

In Scala werden Methodenpaare der Form type T; def <name>: T; def <name>_=(newT: T): Unit als Properties erkannt - ich glaube nicht, dass für andere Formen eine solche Behandlung stattfindet (oder gar generell):

Code: Alles auswählen

scala> class A(x: Int) {
     | private var _internal_x: Int = x
     | def public_x: Int = _internal_x * 2
     | def public_x_=(newX: Int): Unit = _internal_x = newX / 2
     | }
defined class A

scala> var a = new A(54)
a: A = A@3e97cd

scala> a.public_x
res0: Int = 108

scala> a.public_x = 100

scala> a.public_x
res1: Int = 100
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

lunar hat geschrieben:@Darii: Scala erzeugt meines Wissens implizit Zugriffsmethoden für öffentliche Attribute.
Dann ist das Problem nicht existent.
Allerdings würde ich nicht sagen, dass Eigenschaften in Python dieselbe öffentliche Schnittstelle wie Eigenschaften haben. Schließlich unterscheiden sich Eigenschaften als Deskriptoren doch deutlich von normalen Attributen. Nur ist das eben vollkommen egal, weil Zugriffe immer erst zur Laufzeit aufgelöst werden.
Die öffentliche Schnittstelle für Attributzugriffe ist getattr, setattr, getattr bzw. die Äquivalente im Bytecode. Dadurch sind Attribute und Deskriptoren von außen ununterscheidbar.
lunar

@str1442: In Scala wird nach Spezifikation jede Variablendeklaration mittels "var" in Zugriffsmethoden übersetzt:
A variable declaration var x : T is equivalent to declarations of a getter function x
and a setter function x _=, defined as follows:
def x : T
def x _= ( y : T ): Unit
Eigenschaften im eigentlichen Sinne kennt Scala gar nicht, da es auch keine Operatoren gibt. Jeder Operator ist in Scala nichts anderes als ein Methodenaufruf (syntaktisch gibt es nur keinen Unterschied). Daher muss Scala jede Variablendeklaration wie beschrieben übersetzen, da die Zuweisung an die Variable sonst schlichtweg nicht definiert wäre.

@Darii: So gesehen hast Du natürlich recht.
Antworten