Python-Funktion überladen
Ich weiß, dass Python unterstützt nicht die Methode überladen, aber ich habe ein problem, ich kann nicht scheinen, um zu lösen, in einem schönen Pythonic way.
Ich mache ein Spiel, wo ein Charakter braucht, um zu Schießen eine Vielzahl von Kugeln, aber wie Schreibe ich verschiedene Funktionen für die Erstellung dieser Kugeln? Zum Beispiel nehmen wir an ich habe eine Funktion erstellt, die Kugel Reisen von Punkt A nach B mit einer bestimmten Geschwindigkeit. Ich würde eine Funktion schreiben wie dieses:
def add_bullet(sprite, start, headto, speed):
... Code ...
Aber ich möchte schreiben, andere Funktionen für die Erstellung von Aufzählungszeichen wie:
def add_bullet(sprite, start, direction, speed):
def add_bullet(sprite, start, headto, spead, acceleration):
def add_bullet(sprite, script): # For bullets that are controlled by a script
def add_bullet(sprite, curve, speed): # for bullets with curved paths
... And so on ...
Und so weiter mit vielen Variationen. Gibt es einen besseren Weg, es zu tun, ohne so viele keyword-Argumente führen die immer irgendwie hässlich schnell. Die Umbenennung jede Funktion ist ziemlich schlecht, weil man entweder add_bullet1
, add_bullet2
oder add_bullet_with_really_long_name
.
Einige Antworten:
-
Nein, ich kann nicht erstellen Sie eine Kugel in der Hierarchie der Klasse, weil das ist zu langsam. Der eigentliche code für die Verwaltung von Kugeln ist in C und meine Funktionen sind Wrapper um die C-API.
-
Weiß ich über die keyword-Argumente aber die überprüfung für alle möglichen Kombinationen der Parameter ist immer ärgerlich, aber Standard-Argumente helfen zuzuteilen wie
acceleration=0
default-Wert + if + else
, das gleiche zu tun wie C++ zu tun. Dies ist eines der sehr wenigen Dinge, die C++ hat bessere Lesbarkeit als Python... InformationsquelleAutor der Frage Bullets | 2011-06-22
Du musst angemeldet sein, um einen Kommentar abzugeben.
Python unterstützt "Methode ist überladen", wie Sie es darstellen. In der Tat, was Sie gerade beschreiben, ist trivial zu implementieren in Python, in so viele verschiedene Möglichkeiten, aber ich würde gehen mit:
Im obigen code
default
ist eine plausible default-Wert für diese Argumente, oderNone
. Sie können dann rufen Sie die Methode nur mit den Argumenten, die Sie interessiert sind, und Python verwenden Sie die Standardwerte.Könnte man auch etwas wie das hier tun:
Andere alternative ist es, direkt Haken Sie die gewünschte Funktion direkt an die Klasse oder Instanz:
Doch ein anderer Weg ist die Verwendung einer abstract factory pattern:
InformationsquelleAutor der Antwort Escualo
Können Sie "roll-your-own" - Lösung für das überladen von Funktionen. Dies ist kopiert von Guido van Rossum ist der Artikel über multimethods (da gibt es wenig Unterschied zwischen mm und überlastung in python):
Die Verwendung wäre
Meisten Einschränkungen im moment sind:
InformationsquelleAutor der Antwort Alexander Poluektov
Was Sie fordern, heißt multiple dispatch. Sehen Julia Sprache, die Beispiele, die zeigt die verschiedenen Arten von Sendungen.
Jedoch, bevor Sie anzuschauen, müssen wir erst angehen, warum überlastung ist nicht wirklich das, was Sie wollen in python.
Warum Nicht Überladen?
Zuerst muss man verstehen, das Konzept der überlastung und warum es nicht für python.
Python ist eine dynamisch typisierte Sprache, so dass das Konzept der überladung einfach nicht gelten. Jedoch ist nicht alles verloren, denn wir können eine solche alternative Funktionen Laufzeit:
Also sollten wir in der Lage sein zu tun multimethods in python oder, wie es alternativ genannt, multiple dispatch.
Multiple dispatch
Den multimethods sind auch als multiple dispatch:
Python unterstützt dies nicht aus der box1. Aber, wie es geschieht, es ist eine ausgezeichnete python-Paket namens multipledispatch, was genau das macht.
Lösung
Hier ist, wie könnten wir multipledispatch2 - Paket für die Implementierung Ihrer Methoden:
1. Python 3 unterstützt derzeit Einzel-Versand
2. Achten Sie darauf, nicht zu verwenden multipledispatch in einer multi-threaded Umgebung, oder erhalten Sie sonderbare Verhalten.
InformationsquelleAutor der Antwort drozzy
Eine mögliche option ist die Verwendung der multipledispatch Modul wie hier beschrieben:
http://matthewrocklin.com/blog/work/2014/02/25/Multiple-Dispatch
Statt dies zu tun:
Können Sie dies tun:
Mit der daraus resultierenden Verwendung:
InformationsquelleAutor der Antwort Dave C
In Python 3.4 wurde Hinzugefügt PEP-0443. Einzel-Versand generische Funktionen.
Hier ist kurz API-Beschreibung von PEP.
Definieren Sie eine generische Funktion, dekorieren Sie es mit der @singledispatch Dekorateur. Beachten Sie, dass der Versand geschieht auf dem Typ des ersten Arguments. Erstellen Sie Ihre Funktion entsprechend:
Hinzufügen überlastet Implementierungen der Funktion, verwenden Sie die register () - Attribut der generischen Funktion. Dies ist ein Dekorateur, einen Typ-parameter und der Dekoration eine Funktion der Durchführung der operation für diese Art:
InformationsquelleAutor der Antwort Infernion
Diese Art von Verhalten ist in der Regel gelöst (in OOP-Sprachen) - Polymorphismus. Jede Art von Kugel wäre dafür verantwortlich, zu wissen, wie Sie sich bewegt. Zum Beispiel:
Passieren so viele Argumente, um die c_function, die es gibt, dann tun die Aufgabe zu ermitteln, welche c-Funktion aufrufen, basierend auf den Werten in der ersten c-Funktion. So, python sollte immer nur den Aufruf der c-Funktion. Dass eine c-Funktion sucht sich die Argumente, und dann delegieren können andere c-Funktionen angemessen.
Sind Sie im wesentlichen nur mit jeder Unterklasse als eine andere Daten-container, aber durch die Festlegung aller möglichen Argumente auf der Basis der Klasse, die Unterklassen sind frei, Sie zu ignorieren diejenigen, die Sie tun, nichts mit.
Wenn eine neue Art von Kugel kommt, können Sie einfach definieren Sie eine weitere Eigenschaft, die auf der Basis ändern, das eine python-Funktion, so dass es durchläuft die zusätzliche Eigenschaft, und die eine c_function, untersucht die Argumente und die Delegierten entsprechend. Klingt nicht allzu schlecht, denke ich.
InformationsquelleAutor der Antwort Josh Smeaton
Ich denke, Ihre grundlegende Voraussetzung ist, um ein C/C++ - ähnliche syntax in python mit den wenigsten Kopfschmerzen möglich. Obwohl ich mochte Alexander Poluektov Antwort, es funktioniert nicht für die Klassen.
Sollten die folgenden arbeiten für die Klassen. Es funktioniert durch die Unterscheidung von der Anzahl der nicht-Schlüsselwort-Argumente (aber nicht unterstützen, Unterscheidung nach Typ):
Und es kann einfach verwendet werden wie diese:
Ausgabe:
InformationsquelleAutor der Antwort Tim Ludwinski
Durch vorbei Schlüsselwort args.
InformationsquelleAutor der Antwort Nick Radford
Entweder mehrere keyword-Argumente in der definition, oder erstellen Sie eine
Bullet
Hierarchie, deren Instanzen an die Funktion übergeben werden.InformationsquelleAutor der Antwort Ignacio Vazquez-Abrams
Ich denke, ein
Bullet
Klassen-Hierarchie mit den zugehörigen Polymorphismus ist der Weg zu gehen. Sie können effektiv die überlastung der Basisklasse Konstruktor mithilfe einer Metaklasse, so dass die Basisklasse aufrufen die Ergebnisse bei der Schaffung der entsprechenden Unterklasse-Objekt. Nachfolgend finden Sie einige Beispiel-code, verdeutlichen die Essenz dessen, was ich meine.InformationsquelleAutor der Antwort martineau
Verwenden Sie keyword-Argumente mit Standardwerten. E. g.
In der Falle eine gerade Kugel gegen eine gekrümmte Kugel, ich möchte hinzufügen, zwei Funktionen:
add_bullet_straight
undadd_bullet_curved
.InformationsquelleAutor der Antwort Rafe Kettler
überladen von Methoden ist schwierig, in python. Es kann jedoch vorkommen, Verwendung der Weitergabe der dict, list oder primitiven Variablen.
Habe ich versucht etwas für meine Anwendungsfälle, könnte dies hier helfen, Menschen zu verstehen, um eine überlastung der Methoden.
Nehmen wir dein Beispiel:
einer Klasse überlast-Methode mit Aufruf der Methoden aus der anderen Klasse.
übergeben Sie die Argumente aus der remote-Klasse:
ODER
So, die Handhabung ist auf der Liste, Dictionary oder primitiven Variablen von Methode überladen.
probieren Sie es aus für Ihre codes.
InformationsquelleAutor der Antwort shashankS