** kwargs è un antipasto?


15

Abbiamo un sacco di codice nella nostra base di codice interna che chiama le nostre librerie internamente - queste librerie spesso hanno molti argomenti (pensate a matplotlib) e il nostro codice spesso fa solo un compito specifico e passa semplicemente **kwargsalla funzione chiamata successiva.

Per esempio:

def our_method(dataframe, **kwargs):
    result = do_something_with_data(dataframe)
    external_module.draw(result, **kwargs)

Mentre **kwargsci impedisce di ripetere tutti i parametri nella nostra dichiarazione del metodo, rende anche estremamente opachi quali argomenti sono validi quando si chiama our_method- devo sapere quale metodo viene chiamato, che spesso non voglio sapere.

Cosa ne pensi di questo?

Risposte:


15

Come viene utilizzato il tuo codice dagli sviluppatori? In altre parole, cosa fanno esattamente per determinare quali argomenti dovrebbero essere usati e come?

  • Se si basano sulla documentazione generata automaticamente dal tuo codice e il generatore non ha idea di cosa fare **kwargs, questo è davvero problematico. Invece di trovare la lista degli argomenti e il loro significato nella documentazione, non hanno assolutamente alcuna informazione tranne il vago "prende alcuni argomenti".

    Probabilmente questo problema può essere risolto documentando manualmente il metodo, sostituendo la documentazione generata automaticamente. Ciò richiede un lavoro extra da parte dell'implementatore del metodo, ma ricorda, il codice (e la sua documentazione) viene letto molto più frequentemente di quanto sia scritto.

  • Se il codice è la loro documentazione, gli sviluppatori che usano il metodo **kwargsnecessitano di due passaggi aggiuntivi: non solo devono guardare la firma del metodo, ma anche la sua effettiva implementazione, al fine di trovare l'altro metodo che chiama effettivamente. Quindi, devono andare a questo altro metodo per trovare finalmente quello che stavano cercando.

    Ciò non comporta molti sforzi, ma lo sforzo dovrebbe essere ripetuto ancora e ancora. La parte peggiore è che non puoi aiutarli aggiungendo documentazione: se commenti il ​​tuo metodo, elencando gli argomenti reali, c'è un grosso rischio che la prossima versione della libreria che il tuo metodo chiamerà abbia argomenti diversi, e la tua documentazione sarà essere obsoleto, poiché nessuno ricorderà che deve essere aggiornato.

La mia raccomandazione è di fare affidamento **kwargssolo su metodi con portata ridotta. I metodi privati ​​(e per privato in un contesto di Python, intendo i metodi che iniziano per _) che sono usati in alcuni posti della classe sono buoni candidati, per esempio. D'altra parte, i metodi che vengono utilizzati da decine di classi in tutta la base di codice sono candidati molto cattivi.

Dopotutto, non dovrebbe essere necessario uno sforzo eccessivo per riscrivere gli argomenti di un metodo che chiami all'interno del metodo che scrivi. Si spera che la maggior parte dei metodi non prenda più di 6-8 argomenti e, in tal caso, chiediti se non dovresti eseguire il refactoring del codice. In tutti i casi:

  • Rendere espliciti gli argomenti nel tuo metodo non richiede molto sforzo,

  • Potresti voler, in seguito, validare gli argomenti comunque (anche se se fai affidamento solo su questo punto per rendere espliciti gli argomenti, stai violando YAGNI).


Mi piace molto questa risposta e penso che sia una buona risposta. Sfortunatamente, molti dei nostri codici hanno molti metodi pubblici che usano questo modello. Ma ora ho argomentazioni sul fatto che dovremmo cambiarlo (e rilasciare matplotlib, non ho mai visto una "interfaccia" più scadente ..)
Christian Sauer,

3

Se la funzione di livello successivo ha un __doc__, puoi semplicemente copiare __doc__ nella tua nuova funzione.

Per esempio:

def a(x):
    """This function takes one parameter, x, and does nothing with it!"""
    pass

def b(**kwargs):
    a(**kwargs)

b.__doc__=a.__doc__

Questo potrebbe applicarsi in modo ricorsivo e potrebbe essere applicato da un decoratore (che potrebbe essere utile se lo stai facendo in blocco comunque). Anche la stringa __doc__ potrebbe essere manipolata per aggiungere altro alla fine. Ciò significa che i parametri mostrati sarebbero comunque kwargs, ma almeno c'è una documentazione nella guida che descrive i parametri effettivi.

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.