Prototypische Programmierung in Python

8

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.

    
Andrea 07.01.2011, 19:02
quelle

5 Antworten

6

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%     
Lennart Regebro 07.01.2011 20:29
quelle
4

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:

%Vor%

Achten Sie auch auf dies Frage, da es einige Notizen zu alten und neuen Stilobjekten enthält.

    
ffriend 07.01.2011 20:01
quelle
1

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.

    
OneOfOne 07.01.2011 19:17
quelle
1

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).

    
hayavuk 25.11.2012 05:04
quelle
1

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:

%Vor%

Hier ist gist

    
Daniel Mahler 04.01.2016 07:44
quelle