Forum >> Principianti >> Overloading def

Pagina: 1 2 Avanti

Salve a tutti,
Volevo esporvi un mio quesito.

Avrei la necessità di scrivere una funzione che ne wrapperizzi più di una, per capirci meglio una funzione che a seconda di un ingresso type='tipologia' esegua la funzione in un modo piuttosto che in un altro. Ad ogni stringa type possibile corrisponde una funzione di un secondo modulo (modulo che raccoglie tutte queste funzioni).

Esiste un modo un po' più "carino" e meno ripetitivo rispetto alla classica pila di if type=="tipo" else (...). Magari con un dizionario? O sfruttando i __name__ delle def del modulo?

Aggiungo inoltre che tale pila di if mi servirebbe per altre funzioni, dunque preferirei che se dovessi aggiungere una tipologia di comportamento (quindi aggiungere un funzione al modulo che le contiene) si cambiasse automaticamente in tutte le funzioni che wrapperizzano questi type.

Grazie a tutti in anticipo



Scrivi un esempio, magari si capisce meglio ;)
Certamente ;)




minimizzando ai minimi termi una cosa del seguente tipo. Ovviamente le funzioni sono più di una che sfruttano mymodule quindi pensavo a una sorta di registro o sfruttando __name__ delle func non saprei.

import mymodule

def def1(x,y,type='a'):
    if type=='a': return mymodule.func_a(x,y)
    if type=='b': return mymodule.func_b(x,y)
    if type=='c': return mymodule.func_c(x,y)
    if type=='d': return mymodule.func_d(x,y)  
    if type=='e': return mymodule.func_e(x,y)



Quello che cerchi di fare è un'elementare strategia di dispatching. Ora, si può andare nel sofisticato (strategy pattern, observer pattern... al massimo prova a googlare un po') ma in pratica la cosa più naturale, in python, è usare un dizionario (dictionary-based dispatch). Qualcosa come:

def f1(a, b, c): pass
def f2(a, b, c): pass
def f3(a, b, c): pass

DISPATCH_TABLE = {'foo!': f1, 'bar!': f2, 'baz!': f3}
def f(operation, a, b, c):
    return DISPATCH_TABLE[operation](a, b, c)

# quindi adesso
# f('bar!', 1, 2, 3)
# esegue f2(1, 2, 3)
Questo pattern è la risposta standard che si dà (dall'alba dei tempi) a tutti quelli che provengono da un linguaggio con un qualche tipo di switch statement e che ne sentono la mancanza in Python.


Ovviamente la cosa funziona se (come nel mio esempio) tutte le funzioni "figlie" hanno la stessa signature, che si può raccogliere tal quale nella funzione "madre". Se le funzioni hanno signature diverse, allora magari puoi fare dei trucchi con *args e/o **kwargs, ma prima chiediti se ha davvero senso raggrupparle insieme, se sono così diverse.


Ancora una cosa: NON usare "type" nel tuo codice. "Type" è una builtin function in python, e non prendere l'abitudine di sovrascriverla, anche nei casi in cui non è dannoso farlo, come questo.



--- Ultima modifica di RicPol in data 2019-01-16 10:12:15 ---
davvero chiarissimo la soluzione penso sia perfetta per il mio caso! :D




si le funzioni hanno tutte stesso ingresso e stessa uscita cambiando solo le operazioni all'interno quindi la soluzione che mi hai proposto penso sia ottima.




grazie mille! :) :)


Se non vuoi dover tenere allineata la DISPATCH_TABLE e il modulo, e se le funzioni hanno una naming convention comune, puoi anche fare qualcosa tipo:

$ cat mymodule.py 
def func_a(x, y): ...
def func_b(x, y): ...
def func_c(x, y): ...
def func_d(x, y): ...
def func_e(x, y): ...
$ py
>>> import mymodule
>>> def def1(x, y, type_='a'): return getattr(mymodule, 'func_' + type_)(x, y)
... 
>>> def1(1, 2, 'c')



HTH,






THE 🍺-WARE LICENSE (Revision ㊷):
<㎝🐌🐍.🇮🇹> wrote this post. As long as you retain this notice you
can do whatever you want with this stuff. If we meet some day, and you
think this stuff is worth it, you can buy me a 🍺 in return. -- ㎝
ottima idea! si sarebbe davvero comodo che aggiungendo la sola func al modo si aggiornino tutte le funzioni! faccio qualche tentativo e vi farò sapere :D










--- Ultima modifica di Bibo90 in data 2019-01-16 12:03:17 ---
> Se non vuoi dover tenere allineata la DISPATCH_TABLE e il modulo, e se
le funzioni hanno una naming convention comune, puoi anche fare qualcosa
tipo ...

Questa è veramente una cattiva idea, stanne alla larga. E anche se non fosse una cattiva idea (e lo è), tieni conto che tecnicamente questo non è più "semplice" dispatching, è già metaprogrammazione/code inspection. Ora, fare code inspection può essere utile e necessario in certi scenari, ma è una bestia di un altro tipo.






--- Ultima modifica di RicPol in data 2019-01-16 12:25:57 ---
tuttavia mi sorge un dubbio, essendo che il modulo "mymodule" una volta terminata la fase di prototipazione sarà compilato in cython, la funzione getattr funzionerà ugualmente o potrebbe dare dei problemi? :confused:
getattr dovrebbe funzionare senza problemi in cython. Posto che usare getattr nel tuo scenario è una cattiva idea, come detto.










Pagina: 1 2 Avanti



Esegui il login per scrivere una risposta.