Überladene Funktionen in Python?

90

Ist es möglich, Funktionen in Python überladen zu haben? In C # würde ich so etwas machen

void myfunction (int first, string second)
{
//some code
}
void myfunction (int first, string second , float third)
{
//some different code
}

und wenn ich dann die Funktion aufrufe, würde sie zwischen den beiden anhand der Anzahl der Argumente unterscheiden. Ist es möglich, etwas Ähnliches in Python zu tun?

Trcx
quelle
Dies scheint ein möglicher doppelter Beitrag zu sein. Bitte markieren Sie auch nicht als C #, da die Frage nicht mit C # zu tun hat. Funktionsüberladung-in-Python-fehlt
Jethro
Mögliches Duplikat der Funktionsüberladung in Python: Missing
Li0liQ
Mögliches Duplikat der Überladung
Ciro Santilli 法轮功 冠状 病 六四 六四 事件 14.

Antworten:

101

BEARBEITEN Die neuen generischen Funktionen für den Einzelversand in Python 3.4 finden Sie unter http://www.python.org/dev/peps/pep-0443/.

Im Allgemeinen müssen Sie Funktionen in Python nicht überladen. Python ist dynamisch typisiert und unterstützt optionale Argumente für Funktionen.

def myfunction(first, second, third = None):
    if third is None:
        #just use first and second
    else:
        #use all three

myfunction(1, 2) # third will be None, so enter the 'if' clause
myfunction(3, 4, 5) # third isn't None, it's 5, so enter the 'else' clause
agf
quelle
3
Beachten Sie jedoch, dass das Aufrufen verschiedener Funktionen basierend auf der Art der Argumente viel schwieriger (wenn auch nicht unmöglich) ist.
Andrew Jaffe
8
Nun, es gibt einen Unterschied zwischen Überladung / Polymorphismus und Bedingungen. Meinen Sie damit, dass wir den Polymorphysmus nicht brauchen, da wir die Bedingungen haben?
Val
1
@Val Ich sage im Grunde, dass Sie in einer dynamisch typisierten Sprache keine Überladung als Sprachfunktion benötigen, da Sie sie trivial in Code emulieren und so Polymorphismus auf diese Weise erzielen können.
Agf
1
@Val Ich sage, dass zwischen optionalen Argumenten und dynamischen Typen, wie Sie sie in Python haben, keine Überladung der Java-Methode erforderlich ist, um Polymorphismus zu erzielen.
Agf
2
@navidoo Ich würde argumentieren, dass dies keine gute Idee ist - eine Funktion sollte keine völlig anderen Arten von Dingen zurückgeben. Sie können jedoch jederzeit eine lokale Generatorfunktion innerhalb der Hauptfunktion definieren, aufrufen und den resultierenden Generator zurückgeben - von außen ist dies dieselbe, als ob die Hauptfunktion ein Generator wäre. Beispiel hier.
agf
50

In normalem Python können Sie nicht tun, was Sie wollen. Es gibt zwei enge Annäherungen:

def myfunction(first, second, *args):
    # args is a tuple of extra arguments

def myfunction(first, second, third=None):
    # third is optional

Wenn Sie dies jedoch wirklich tun möchten, können Sie es auf jeden Fall zum Laufen bringen (auf die Gefahr hin, die Traditionalisten zu beleidigen; o). Kurz gesagt, Sie würden eine wrapper(*args)Funktion schreiben , die die Anzahl der Argumente und Delegaten entsprechend überprüft. Diese Art von "Hack" wird normalerweise über Dekorateure durchgeführt. In diesem Fall könnten Sie etwas erreichen wie:

from typing import overload

@overload
def myfunction(first):
    ....

@myfunction.overload
def myfunction(first, second):
    ....

@myfunction.overload
def myfunction(first, second, third):
    ....

und Sie würden dies implementieren, indem Sie die overload(first_fn) Funktion (oder den Konstruktor) dazu bringen, ein aufrufbares Objekt zurückzugeben, bei dem die __call__(*args) Methode die oben erläuterte Delegierung ausführt und die overload(another_fn) Methode zusätzliche Funktionen hinzufügt, an die delegiert werden kann.

Ein Beispiel für etwas Ähnliches finden Sie hier http://acooke.org/pytyp/pytyp.spec.dispatch.html aber das überlädt Methoden nach Typ. es ist ein sehr ähnlicher Ansatz ...

UPDATE: und etwas Ähnliches (unter Verwendung von Argumenttypen) wird zu Python 3 hinzugefügt - http://www.python.org/dev/peps/pep-0443/

Andrew Cooke
quelle
Das rangeeingebaute Gerät verwendet Überlastung. Ist es also wirklich ein Hack? github.com/python/typeshed/blob/master/stdlib/2and3/…
CptJero
9

Ja es ist möglich. Ich habe den folgenden Code in Python 3.2.1 geschrieben:

def overload(*functions):
    return lambda *args, **kwargs: functions[len(args)](*args, **kwargs)

Verwendung:

myfunction=overload(no_arg_func, one_arg_func, two_arg_func)

Beachten Sie, dass das von den overloadFunktionen zurückgegebene Lambda die aufzurufende Funktion abhängig von der Anzahl der unbenannten Argumente auswählt.

Die Lösung ist nicht perfekt, aber im Moment kann ich nichts besseres schreiben.

GingerPlusPlus
quelle
1

Nicht direkt möglich. Sie können jedoch explizite Typprüfungen für die angegebenen Argumente verwenden, obwohl dies im Allgemeinen verpönt ist.

Python ist dynamisch. Wenn Sie sich nicht sicher sind, was ein Objekt tun kann, versuchen Sie einfach: und rufen Sie eine Methode auf, außer: Fehler.

Wenn Sie nicht nach Typen, sondern nur nach Anzahl der Argumente überladen müssen, verwenden Sie Schlüsselwortargumente.

Jürgen Strobel
quelle
3
Ich glaube nicht, dass er über optionale Argumente Bescheid wusste.
Agf
0

Überladungsmethoden sind in Python schwierig. Es kann jedoch sinnvoll sein, das Diktat, die Liste oder die primitiven Variablen zu übergeben.

Ich habe etwas für meine Anwendungsfälle ausprobiert. Dies könnte hier helfen, die Leute zu verstehen, die die Methoden überladen.

Nehmen wir das Beispiel, das in einem der Stackoverflow-Threads verwendet wird:

Eine Klassenüberladungsmethode mit Aufruf der Methoden aus verschiedenen Klassen.

def add_bullet(sprite=None, start=None, headto=None, spead=None, acceleration=None):

Übergeben Sie die Argumente der Remote-Klasse:

add_bullet(sprite = 'test', start=Yes,headto={'lat':10.6666,'long':10.6666},accelaration=10.6}

ODER add_bullet(sprite = 'test', start=Yes,headto={'lat':10.6666,'long':10.6666},speed=['10','20,'30']}

Daher wird die Behandlung für Listen-, Wörterbuch- oder primitive Variablen durch Überladen von Methoden erreicht.

Probieren Sie es für Ihre Codes aus

shashankS
quelle