Funzioni sovraccaricate in Python?


91

È possibile avere funzioni sovraccariche in Python? In C # farei qualcosa di simile

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

e poi quando chiamo la funzione si differenzia tra i due in base al numero di argomenti. È possibile fare qualcosa di simile in Python?


Questo sembra essere un possibile post duplicato. Inoltre, non contrassegnare come C # poiché la domanda non ha a che fare con C #. funzione-sovraccarico-in-python-mancante
Jethro

possibile duplicato del sovraccarico
Li0liQ

Risposte:


103

EDIT Per le nuove funzioni generiche a invio singolo in Python 3.4, vedere http://www.python.org/dev/peps/pep-0443/

In genere non è necessario sovraccaricare le funzioni in Python. Python è tipizzato dinamicamente e supporta argomenti opzionali per le funzioni.

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

3
Si noti però che chiamare funzioni diverse in base al tipo di argomenti è molto più difficile (sebbene non impossibile).
Andrew Jaffe,

9
Bene, c'è una differenza tra sovraccarico / polimorfismo e condizionali. Vuoi dire che non abbiamo bisogno del polimorfismo poiché abbiamo i condizionali?
Val

1
@Val Sto dicendo, fondamentalmente, che in un linguaggio digitato dinamicamente non è necessario sovraccaricare come caratteristica del linguaggio perché puoi banalmente emularlo nel codice, e così puoi ottenere il polimorfismo in questo modo.
agf

1
@Val Sto dicendo che tra argomenti opzionali e tipi dinamici nel modo in cui li hai in Python, non è necessario il sovraccarico del metodo in stile Java per ottenere il polimorfismo.
agf

3
@navidoo Direi che non è una buona idea: una funzione non dovrebbe restituire tipi di cose completamente diversi. Tuttavia, puoi sempre definire una funzione di generatore locale all'interno della funzione principale, chiamarla e restituire il generatore risultante: dall'esterno sarà come se la funzione principale fosse un generatore. Esempio qui.
agf

50

in normale python non puoi fare quello che vuoi. ci sono due approssimazioni ravvicinate:

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

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

tuttavia, se vuoi davvero farlo, puoi certamente farlo funzionare (a rischio di offendere i tradizionalisti; o). in breve, si scriverebbe una wrapper(*args)funzione che controlla il numero di argomenti e delegati come appropriato. questo tipo di "hack" viene solitamente eseguito tramite decoratori. in questo caso potresti ottenere qualcosa come:

from typing import overload

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

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

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

e lo implementeresti facendo in modo che la overload(first_fn) funzione (o il costruttore) restituisca un oggetto richiamabile in cui il __call__(*args) metodo esegue la delega spiegata sopra e il overload(another_fn) metodo aggiunge funzioni extra a cui è possibile delegare.

puoi vedere un esempio di qualcosa di simile qui http://acooke.org/pytyp/pytyp.spec.dispatch.html ma questo è l'overloading dei metodi per tipo. è un approccio molto simile ...

AGGIORNAMENTO: e qualcosa di simile (usando i tipi di argomento) viene aggiunto a python 3 - http://www.python.org/dev/peps/pep-0443/


Il rangebuiltin usa il sovraccarico, quindi è davvero un hack? github.com/python/typeshed/blob/master/stdlib/2and3/…
CptJero

9

Si è possibile. Ho scritto il codice di seguito in Python 3.2.1:

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

Utilizzo:

myfunction=overload(no_arg_func, one_arg_func, two_arg_func)

Si noti che il lambda restituito dalle overloadfunzioni sceglie la funzione da chiamare a seconda del numero di argomenti senza nome .

La soluzione non è perfetta, ma al momento non riesco a scrivere di meglio.


1

Non possibile direttamente. Tuttavia, è possibile utilizzare controlli di tipo espliciti sugli argomenti forniti, sebbene questo sia generalmente disapprovato.

Python è dinamico. Se non sei sicuro di cosa possa fare un oggetto, prova: e chiama un metodo su di esso, quindi tranne: errori.

Se non è necessario eseguire l'overload in base ai tipi ma solo al numero di argomenti, utilizzare gli argomenti delle parole chiave.


3
Non credo che sapesse di argomenti opzionali.
agf

0

sovraccaricare i metodi è complicato in Python. Tuttavia, potrebbe esserci l'uso del passaggio di dict, list o variabili primitive.

Ho provato qualcosa per i miei casi d'uso, questo potrebbe aiutare qui a capire le persone per sovraccaricare i metodi.

Prendiamo l'esempio di utilizzo in uno dei thread stackoverflow:

un metodo di sovraccarico della classe con la chiamata ai metodi di una classe diversa.

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

passare gli argomenti dalla classe remota:

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

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

Quindi, la gestione è stata ottenuta per lista, dizionario o variabili primitive dal sovraccarico del metodo.

provalo per i tuoi codici

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.