2012-04-18 10 views
90

Sto cercando di implementare overloading dei metodi in Python:Come utilizzo l'overloading dei metodi in Python?

class A: 
    def stackoverflow(self):  
     print 'first method' 
    def stackoverflow(self, i): 
     print 'second method', i 

ob=A() 
ob.stackoverflow(2) 

ma l'uscita è second method 2; simile:

class A: 
    def stackoverflow(self):  
     print 'first method' 
    def stackoverflow(self, i): 
     print 'second method', i 

ob=A() 
ob.stackoverflow() 

Traceback (most recent call last): 
    File "my.py", line 9, in <module> 
    ob.stackoverflow() 
TypeError: stackoverflow() takes exactly 2 arguments (1 given) 

Come faccio a fare questo lavoro?

+18

In Python, pensare di metodi come un insieme particolare di "* * attributi", e non ci può essere un solo "attributo * *" (e quindi un metodo) di un nome per un oggetto. L'ultimo metodo * sovrascrive * qualsiasi metodo precedente. In Java, i metodi non sono cittadini di prima classe (non sono "attributi di oggetti"), ma sono piuttosto invocati da "invio di messaggi" che sono risolti staticamente in base al tipo più vicino (che è il punto in cui * overloading * entra). –

+2

vedere anche http://stackoverflow.com/questions/733264/function-overloading-in-python-missing – agf

+2

e http://stackoverflow.com/questions/6434482/python-function-overloading – agf

risposta

109

E 'il metodo sovraccarico non metodo prioritario. E in Python, è fare tutto in una sola funzione:

class A: 

    def stackoverflow(self, i='some_default_value'):  
     print 'only method' 

ob=A() 
ob.stackoverflow(2) 
ob.stackoverflow() 

Non si possono avere due metodi con lo stesso nome in Python - e che non è necessario a.

Vedere la sezione Default Argument Values del tutorial Python. Vedere "Least Astonishment" and the Mutable Default Argument per un errore comune da evitare.

Modifica: Vedere PEP 443 per informazioni sulle nuove funzioni generiche di invio singolo in Python 3.4.

+55

_e non hai bisogno di -_ IMHO a volte sarebbe molto utile avere un overload di metodi come ad es in C++. Ok, non è "necessario" nel senso che non può essere fatto usando altri costrutti - ma renderebbe alcune cose più facili e semplici. –

+3

@AndreasFlorath Non sono d'accordo. Impara ad amare la digitazione anatra e scrivi ogni metodo in modo che faccia una sola cosa e non ci sia bisogno di sovraccaricare i metodi. – agf

+0

sì, ne ho bisogno, perché scrivo in C++ e quindi penso in C++. capito ora – zinking

12

Penso che la parola che stai cercando sia "sovraccarico". Non esiste alcun overload di metodi in python. È tuttavia possibile utilizzare gli argomenti predefiniti, come segue.

def stackoverflow(self, i=None): 
    if i != None:  
     print 'second method', i 
    else: 
     print 'first method' 

Quando si passa un argomento che seguirà la logica della prima condizione ed eseguire la prima istruzione print. Quando non si passa nessun argomento, passerà alla condizione else ed eseguirà la seconda istruzione di stampa.

33

In Python, non si fanno le cose in questo modo. Quando le persone lo fanno in linguaggi come Java, in genere vogliono un valore predefinito (se non lo fanno, in genere vogliono un metodo con un nome diverso). Quindi, in Python, you can have default values.

class A(object): # Remember the ``object`` bit when working in Python 2.x 

    def stackoverflow(self, i=None): 
     if i is None: 
      print 'first form' 
     else: 
      print 'second form' 

Come si può vedere, è possibile utilizzare questo per innescare comportamenti separato piuttosto che semplicemente avere un valore predefinito.

>>> ob = A() 
>>> ob.stackoverflow() 
first form 
>>> ob.stackoverflow(2) 
second form 
+1

Principalmente 'Nessuna' è utile quando si desidera un valore predefinito mutabile. Il comportamento separato dovrebbe essere in funzioni separate. – agf

+0

@agf: 'None' può anche essere utile come valore predefinito originale. –

+0

Sì, ma mi riferivo ad usarlo come valore sentinella, che è il modo in cui lo si utilizza nella risposta, e come penso che il mio commento chiarisca. – agf

7

In Python, lo si farebbe con un argomento predefinito.

class A: 

    def stackoverflow(self, i=None):  
     if i == None: 
      print 'first method' 
     else: 
      print 'second method',i 
20

Non è possibile, non è mai necessario e non lo si desidera.

In Python, tutto è un oggetto. Le classi sono cose, quindi sono oggetti. Quindi sono metodi.

C'è un oggetto chiamato A che è una classe. Ha un attributo chiamato stackoverflow. Può avere solo uno di questi attributi.

Quando si scrive def stackoverflow(...): ..., ciò che accade è che si crea un oggetto che è il metodo e assegnarlo all'attributo stackoverflow di A. Se si scrivono due definizioni, la seconda sostituisce la prima, allo stesso modo in cui il compito si comporta sempre.

Inoltre, non si desidera scrivere codice che faccia il più selvaggio dei tipi di cose a cui viene talvolta utilizzato il sovraccarico. Non è così che funziona la lingua.

Invece di cercare di definire una funzione separata per ogni tipo di cosa che potrebbe essere dato (che ha poco senso dal momento che non si specificano i tipi di parametri di funzione in ogni caso), smettere di preoccuparsi di ciò che le cose sono e inizio pensando a cosa possono fare do.

Non solo non è possibile scrivere uno separato per gestire una tupla contro un elenco, ma anche non si desidera o è necessario.

Tutto ciò che si fa è sfruttare il fatto che entrambi sono, ad esempio, iterabili (ad esempio, è possibile scrivere for element in container:). (Il fatto che non siano direttamente correlati per eredità è irrilevante.)

10

Scrivo la mia risposta in Python 3.2.1.

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

Come funziona:

  1. overload prende qualsiasi quantità di oggetti chiamabili e li memorizza in tuple functions, quindi restituisce lambda.
  2. Il lambda accetta qualsiasi argomento, quindi restituisce il risultato della funzione di chiamata memorizzata in functions[number_of_unnamed_args_passed] chiamata con argomenti passati al lambda.

Usage:

class A: 
    stackoverflow=overload(     \ 
     None, \ 
     #there is always a self argument, so this should never get called 
     lambda self: print('First method'),  \ 
     lambda self, i: print('Second method', i) \ 
    ) 
+0

questa mi sembra la soluzione più elegante. – jitter

+0

elegante uno +1. –

5

Proprio imbattuto in questo https://github.com/bintoro/overloading.py per qualcuno che possa essere interessato.

Dal readme del repository legato:

sovraccarico è un modulo che fornisce la funzione dispacciamento, in base i tipi e numero di argomenti di runtime.

Quando viene richiamata una funzione sovraccaricata, il dispatcher confronta gli argomenti forniti con le firme delle funzioni disponibili e chiama l'implementazione che fornisce la corrispondenza più precisa.

Caratteristiche

convalida Funzione su regole di registrazione e risoluzione dettagliata garantire un unico, risultato ben definito in fase di esecuzione. Implementa il caching della risoluzione delle funzioni per grandi prestazioni. Supporta i parametri opzionali (valori predefiniti) nelle firme delle funzioni. Valuta entrambi gli argomenti posizionali e di parola chiave quando risolve la corrispondenza migliore. Supporta le funzioni di fallback e l'esecuzione di codice condiviso. Supporta il polimorfismo dell'argomento . Supporta classi ed ereditarietà, compresi i metodi di classe e i metodi statici.

13

È inoltre possibile utilizzare pythonlangutil:

from pythonlangutil.overload import Overload, signature 

class A: 
    @Overload 
    @signature() 
    def stackoverflow(self):  
     print 'first method' 

    @stackoverflow.overload 
    @signature("int") 
    def stackoverflow(self, i): 
     print 'second method', i 
+0

Penso che sia l'unica risposta valida alla domanda. Vorrei raddoppiare se potessi. – Michael

11

scrivo la mia risposta in Python 2.7:

In Python, overloading dei metodi non è possibile; se vuoi davvero accedere alla stessa funzione con caratteristiche diverse, ti suggerisco di andare a scavalcare il metodo.

class Base(): # Base class 
    '''def add(self,a,b): 
     s=a+b 
     print s''' 

    def add(self,a,b,c): 
     self.a=a 
     self.b=b 
     self.c=c 

     sum =a+b+c 
     print sum 

class Derived(Base): # Derived class 
    def add(self,a,b): # overriding method 
     sum=a+b 
     print sum 



add_fun_1=Base() #instance creation for Base class 
add_fun_2=Derived()#instance creation for Derived class 

add_fun_1.add(4,2,5) # function with 3 arguments 
add_fun_2.add(4,2) # function with 2 arguments 
+0

buon lavoro @Matt Grazie –

7

In Python, il sovraccarico non è un concetto applicato. Tuttavia, se si sta cercando di creare un caso in cui, per esempio, si desidera uno di inizializzazione da eseguire se si passa un argomento di tipo foo e un altro inizializzatore per un argomento di tipo bar poi, dal momento che tutto in Python è gestito come oggetto, è può controllare il nome del tipo di classe dell'oggetto passato e scrivere la gestione condizionale basata su quello.

class A: 
    def __init__(self, arg) 
     # Get the Argument's class type as a String 
     argClass = arg.__class__.__name__ 

     if argClass == 'foo': 
     print 'Arg is of type "foo"' 
     ... 
     elif argClass == 'bar': 
     print 'Arg is of type "bar"' 
     ... 
     else 
     print 'Arg is of a different type' 
     ... 

Questo concetto può essere applicato a più scenari diversi attraverso diversi metodi, se necessario.

Problemi correlati