Warum brauchst du "Selbst"? in Python auf Instanzvariablen verweisen?

13

Ich habe in einer Reihe von Sprachen wie Java, Ruby, Haskell und Python programmiert. Aufgrund verschiedener Projekte, an denen ich arbeite, muss ich täglich zwischen vielen Sprachen wechseln. Das Problem ist nun, dass ich oft vergesse, selfals ersten Parameter in den Funktionsdefinitionen in Python zu schreiben. Dies gilt auch für das Aufrufen von Methoden für dasselbe Objekt.

Trotzdem bin ich ziemlich erstaunt über diesen Ansatz von Python. Grundsätzlich müssen wir mehr eingeben, um die Dinge zu erledigen. In Sprachen wie Java und Ruby werden Dinge einfach gemacht, indem automatisch auf die Variablen im aktuellen Objekt verwiesen wird.

Meine Frage ist, warum das selfnotwendig ist? Ist es eine reine Stilwahl oder gibt es einen Grund, warum Python Sie nicht auslassen kann, selfwie Java und C ++ Sie weglassen this?

vivek
quelle
1
@gnat jetzt nur Profis, und im Ernst, es ist eine gute Frage, die mich seit ein paar Tagen nervt, bitte töte sie nicht durch Abstimmungen.
Vivek
2
Diese Frage wurde von stackoverflow.com/questions/2709821/… mehr als gründlich behandelt .
David Arno
Mein Verständnis ist, dass es auf dem C-Stil basiert, einen Zeiger auf eine Struktur als erstes Argument zu übergeben.
Dannnno

Antworten:

23

1) Warum ist selfein expliziter Parameter in Methodensignaturen erforderlich?

Weil Methoden Funktionen sind und foo.bar(baz)nur syntaktischer Zucker für bar(foo, baz). Klassen sind nur Wörterbücher, in denen einige der Werte Funktionen sind. (Konstruktoren sind auch nur Funktionen, weshalb Python nicht benötigt wird. new) Man kann sagen, dass Python deutlich macht, dass Objekte aus einfacheren Komponenten erstellt werden. Dies steht im Einklang mit der Philosophie "explizit ist besser als implizit".

Im Gegensatz dazu sind Objekte in Java wirklich magisch und können nicht auf einfachere Komponenten in der Sprache reduziert werden. In Java (zumindest bis Java 8) ist eine Funktion immer eine Methode, die einem Objekt gehört, und diese Eigenschaft kann aufgrund der statischen Natur der Sprache nicht geändert werden. Daher gibt es keine Unklarheit darüber, worauf es sich thisbezieht, daher ist es sinnvoll, es implizit definieren zu lassen.

JavaScript ist ein Beispiel für eine Sprache, die implizit thiswie Java ist, bei der Funktionen jedoch getrennt von Objekten wie in Python vorhanden sein können. Dies führt zu großer Verwirrung darüber, worauf es thisankommt, wenn Funktionen in verschiedenen Kontexten herumgereicht und aufgerufen werden. Viele denken instinktiv, dass sie thissich auf eine intrinsische Eigenschaft der Funktion beziehen müssen, während sie tatsächlich nur durch die Art und Weise bestimmt wird, wie die Funktion aufgerufen wird. Ich glaube, dass thisein expliziter Parameter wie in Python dies viel weniger verwirrend machen würde.

Einige andere Vorteile des expliziten selfParameters:

  • Dekorateure sind nur Funktionen, die andere Funktionen einschließen. Da Methoden nur Funktionen sind, funktionieren Dekoratoren bei Methoden genauso gut. Wenn es eine Art implizites Selbst gäbe, würden Dekorateure nicht transparent an Methoden arbeiten.

  • Klassenmethoden und statische Methoden akzeptieren keinen Instanzparameter. Klassenmethoden verwenden eine Klasse als erstes Argument (normalerweise aufgerufen cls). Das explizite selfoder die clsParameter machen viel klarer, was los ist und worauf Sie in der Methode zugreifen können.

2) Warum müssen Instanzvariablen immer mit "qualifiziert werden self.?

In Java müssen Sie Mitgliedsvariablen nicht " this." voranstellen , in Python self.ist jedoch immer " " erforderlich. Der Grund dafür ist, dass Python keine explizite Syntax zum Deklarieren von Variablen hat. Daher kann nicht festgestellt werden, ob x = 7eine neue lokale Variable deklariert oder einer Mitgliedsvariablen zugewiesen werden soll. Das Angeben self.löst diese Mehrdeutigkeit.

JacquesB
quelle
Die implizite Referenz von Mitgliedsvariablen (ohne self., wie Java) ist grundsätzlich nicht mit den Gültigkeitsbereichsregeln kompatibel, und wenn Sie dort explizit sein müssen, macht es keinen Sinn mehr, implizit über den Parameter zu sein.
Jan Hudec
@ JanHudec: Gut, Punkt. Ich habe es der Antwort hinzugefügt.
JacquesB
6

Es gibt einen ziemlich einfachen Grund, warum AFAIK weder im Cross-Site-Duplikat noch hier wirklich angesprochen wurde: Python begann als prozedurale Sprache. Es basierte auf ABC, ebenfalls eine prozedurale Sprache.

Die Objektorientierung wurde später hinzugefügt, und als sie hinzugefügt wurde, wollte Guido van Rossum die minimal mögliche Anzahl von Funktionen hinzufügen, um das Design von Python einfach zu halten. Python hatte bereits dicts und Funktionen. Warum also der Sprache etwas völlig Neues hinzufügen, wenn ein Objekt einfach dictaus Slots und eine Klasse einfach dictaus Funktionen bestehen kann? Eine Methode kann als teilweise angewendete Funktion interpretiert werden, die über ein einzelnes unterschiedliches Argument schließt. Und genau so werden Methoden in Python implementiert: Sie sind es nicht. Sie sind nur Funktionen, die ein besonders unterschiedliches Argument erhalten.

Jörg W Mittag
quelle
Ich glaube, Python hat OO unterstützt und hatte Klassen und Vererbung von der ersten veröffentlichten Version an. Zumindest sagt mir das Wikipedia. Aber van Rossums Prozess bei der anfänglichen Gestaltung der Sprache könnte so gewesen sein, wie Sie es beschrieben haben.
JacquesB
Vielen Dank für den Link, das ist wirklich eine interessante Lektüre.
JacquesB
2

Hier sind meine Schlussfolgerungen, die auf den obigen Antworten basieren und die eigenen Streifzüge des Guido zu diesem Thema lesen :

Die große Idee

Funktionen sind die wichtigen Bausteine ​​in Python (oder wir sollten den einzigen sagen), tatsächlich emulieren wir OOP mithilfe von Funktionen.

Da eine Klasse nichts anderes als ein Wörterbuch von Funktionen ist, können wir zur Laufzeit jede Funktion an jede Klasse anhängen. Grundsätzlich ist es aus diesem Grund, die Funktionen zur Laufzeit herumzuwerfen, können wir Dinge wie Monkey Patching machen . Hier der selfParameter, der den parametrischen Polymorphismus unterstützt.

vivek
quelle
1
Selbst beantwortete Fragen werden empfohlen, wenn Ihre Antwort eine qualitativ hochwertige Antwort ist. Wenn ich Ihre Antwort hier mit den anderen Antworten vergleiche, frage ich mich, warum Sie das Gefühl hatten, dies hinzufügen zu müssen. Die anderen Antworten gehen tiefer und fügen mehr Details hinzu als Ihre Antwort.
1
@ GlenH7 Die Antwort war nur als Referenz, weil ich jedes Mal nicht kommen und die Antwort aller immer wieder lesen kann. Sagen Sie mir in Bezug auf die Qualität, ob Informationen irreführend sind. Wie auch immer, ich warte in der Regel 2-3 Tage, um eine Antwort zu akzeptieren.
Vivek
Down Voting wird zu einer billigen Währung und jeder hier gibt sie mit beiden Händen aus, ohne ihre Bedeutung zu kennen. Ist dir klar, wenn jemand hierher kommt, würde diese Antwort, die abgestimmt wurde, davon ausgehen, dass sie falsch ist?
Vivek