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.
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?
#!/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()
/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.
/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.
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.
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.
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.
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.
@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.
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):
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
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.
@str1442: In Scala wird nach Spezifikationjede 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.