Javascript verwendet ein prototypbasiertes Modell für seine Objekte. Trotzdem ist die Sprache sehr flexibel und es ist leicht, in ein paar Zeilen Funktionen zu schreiben, die andere Konstrukte ersetzen. Zum Beispiel kann man eine class
-Funktion erstellen, die das Verhalten der Standardklasse emuliert, einschließlich Vererbung oder private Mitglieder. Oder man kann funktionale Werkzeuge mimzieren, indem man zum Beispiel eine Funktion curry
schreibt, die eine Funktion und einige ihrer Argumente übernimmt und die teilweise angewandte Funktion zurückgibt.
Ich habe mich gefragt, ob es möglich ist, das Gegenteil zu tun und die prototypische Methode in mehr klassischen Sprachen nachzuahmen. Insbesondere habe ich ein wenig darüber nachgedacht, ob es möglich ist, Prototypen in Python zu imitieren, aber die fehlende Unterstützung für anonyme Funktionen (allgemeiner als Lambdas) lässt mich stecken.
Ist es möglich, einige Funktionen zu schreiben, um Propotypen in klassenbasierten Sprachen nachzuahmen, insbesondere in Python?
BEARBEITEN Lassen Sie mich ein Beispiel geben, wie man so etwas implementieren könnte (aber ich bin nicht wirklich in der Lage, alles zu tun).
Erstens ist das Python-Wörterbuch, das Javascript-Objekten am ähnlichsten ist. So könnten wir einfache Objekte wie
haben %Vor%Natürlich wollen wir eine Methode hinzufügen, und das ist kein Problem, solange die Methode in ein Lambda
passt %Vor%So können wir jetzt zum Beispiel anrufen
%Vor% Nun wenn wir willkürliche Funktionen als Methoden hatten, könnten wir so weitermachen. Zuerst brauchen wir die Funktionen in foo
, um Zugriff auf foo
selbst zu haben; sonst sind sie nur gewöhnliche Funktionen und keine Methoden.
Ich denke, man könnte dies tun, indem man eine makeObject
-Funktion auf foo
anwendet, die foo
-Werte durchläuft und, wenn sie einen Wert findet, der aufrufbar ist, ihr __call__
-Attribut ändert, um foo
as zu übergeben sein erstes Argument.
In diesem Stadium würden wir selbststehende Objekte haben, die deklariert werden können, ohne dass Klassen erstellt werden müssen.
Dann müssen wir foo
einen Prototyp geben können, der als zweites Argument der Funktion makeObject
übergeben werden kann. Die Funktion sollte foo.__getattr__
und foo.__setattr__
folgendermaßen ändern: Wenn das Attribut nicht in foo
gefunden wird, sollte es in foo.prototype
gesucht werden.
Also, ich denke, ich wäre in der Lage, dies zu implementieren, erwarte nur eines: Ich kann keine Methoden für komplizierter erklären als Lambdas, außer sie vorher zu deklarieren und sie an mein Objekt anzuhängen. Das Problem ist das Fehlen anonymer Funktionen. Ich fragte hier, weil vielleicht ein Python-Guru einen cleveren Weg finden könnte, dies zu umgehen.
Es ist viel einfacher in Python als in JS. Ihr JS-Code könnte in Python mit diesem ersetzt werden:
%Vor%Dann können Sie Methoden auch dynamisch hinzufügen
%Vor%Für Methoden, die komplizierter sind als Lambdas, deklarieren Sie sie als Funktionen, und sie haben Zugriff auf foo selbst, keine Probleme:
%Vor%Oder für die Sache:
%Vor%Selbe Sache.
Wie Sie sehen, ist das, was Ihr Beispiel in Python macht, fast lächerlich einfach. Die Frage ist warum . :) Ich meine, das wäre besser:
%Vor% Jedes Mal, wenn Sie eine Eigenschaft des Python-Objekts lesen, wird die Methode __getattribute__
aufgerufen, sodass Sie sie überladen und den Zugriff auf die Attribute des Objekts vollständig steuern können. Für Ihre Aufgabe kann jedoch eine etwas andere Funktion - __getattr__
- verwendet werden. Im Gegensatz zu __getattribute__
wird only aufgerufen, wenn die normale Suche nach einem Attribut fehlgeschlagen ist, d. H. Gleichzeitig, wenn die Prototyp-Suche in JavaScript gestartet wird. Hier ist die Verwendung:
Achten Sie auch auf dies Frage, da es einige Notizen zu alten und neuen Stilobjekten enthält.
Kurze Version, ja, aber es ist ein bisschen komplizierter als JS
.
Von Metaklassen-Programmierung in Python :
%Vor%Überprüfen Sie auch Was ist eine Metaklasse in Python .
Bearbeiten : Prüfe OO auf Prototypenbasis , was am nächsten kommt get, aber es kommt immer darauf an, entweder ein Lambda zu verwenden oder einfach die Funktion außerhalb zu definieren und einen Zeiger auf das Klassenobjekt hinzuzufügen.
Ich weiß, das ist ziemlich alt, aber ich würde meine $ .02 hinzufügen:
Das einzige Problem hier ist das Hinzufügen von Methoden. JavaScript hat eine viel elegantere Syntax mit seinen Funktionsliteralen, und es ist wirklich schwer, das zu übertreffen. Lambda's schneiden es nicht ganz ab. Meine Lösung bestand also darin, eine unbeholfene method
-Methode zum Hinzufügen von Methoden hinzuzufügen.
Doctests sind im Geiste enthalten, und alles funktioniert.
BEARBEITEN:
Das aktualisierte Gist verwendet nicht mehr method
Instanzmethode. Allerdings müssen wir die Funktion vorher noch definieren.
Jedenfalls ist der wichtigste Teil des prototypischen Objektmodells in diesem Kern implementiert. Andere Dinge sind einfach syntaktischer Zucker (wäre schön, sie zu haben, aber es bedeutet nicht, dass das prototypische Objektmodell nicht verwendet werden kann).
Diese Implementierung enthält eine wichtige Verbesserung gegenüber ansonsten ähnlichen Implementierungen in anderen Antworten und im Internet: die korrekte Vererbung von Methoden aus dem Prototyp. Wenn ein vom Prototyp erhaltener Wert eine gebundene Instanzmethode ist - und um seltsame Eckenfälle abzudecken, ist die Methode auch tatsächlich an diesen Prototyp gebunden - dann wird die zugrundeliegende Funktion der Methode extrahiert und eine neue Methode, die diese Funktion an das aufrufende Objekt bindet zurückgegeben
%Vor% Dies sollte die prototypische Vererbung vollständig implementieren, wie ich es verstehe.
Eine Einschränkung besteht darin, dass von Proto stammende Klassen zuerst Proto in ihrer MRO haben müssen, da __new__
und __init__
den Prototyp als ersten Parameter haben, den sie fallen lassen, wenn sie an super
delegieren.
Hier ist ein Anwendungsbeispiel:
Hier ist gist
Tags und Links python javascript inheritance prototypal-inheritance prototype