Decoratore che cambia la firma: documenta adeguatamente argomenti aggiuntivi

6

Diciamo che ho un decoratore personalizzato e voglio che gestisca correttamente la docstring della funzione decorata. Il problema è: il mio decoratore aggiunge una discussione.

from functools import wraps

def custom_decorator(f):
    @wraps(f)
    def wrapper(arg, need_to_do_more):
        '''
        :param need_to_do_more: if True: do more
        '''
        args = do_something(arg)

        if need_to_do_more:
            args = do_more(args)

        return f(args)

    return wrapper

Puoi vedere che l'argomento non è effettivamente passato alla funzione decorata, ma usato dal wrapper - che può o non può non essere rilevante qui.

Come posso gestire correttamente la documentazione dell'argomento aggiuntivo? È una buona pratica per un wrapper prendere un argomento aggiuntivo, o dovrei evitarlo?

O dovrei piuttosto usare una soluzione diversa, come:

  • rendere il wrapper una semplice funzione di ordine superiore, con la funzione che chiama passato come terzo argomento
  • refactoring del wrapper in due funzioni separate?
posta vikingr 21.12.2015 - 20:22
fonte

1 risposta

1

La modifica della firma del metodo utilizzando il decoratore è qualcosa che nella maggior parte dei casi viola Principio di astensione :

The Principle of Least Astonishment states that the result of performing some operation should be obvious, consistent, and predictable, based upon the name of the operation and other clues.

Le eccezioni che potrei trovare sono:

  • decoratore nel suo nome indica chiaramente che la firma del metodo è cambiata. Esempio di tale decoratore è @property .
  • il metodo decorato non è inteso per essere invocato direttamente dal codice client
  • decoratore viene utilizzato per un qualche tipo di adattamento (come Pattern adattatore )

Tuttavia, di solito i decoratori sono solitamente implementati per le funzioni di decorazione (come in pattern Decorator , sebbene gli autori della funzione di decorazione < a href="https://www.python.org/dev/peps/pep-0318/#on-the-name-decorator"> si oppose a queste somiglianze ), il che implica che la firma del metodo (inclusa la lista di parametri) non è cambiato.

In alternativa all'aggiunta implicita di un nuovo parametro, propongo di renderlo esplicito - qualsiasi funzione decorata deve dichiarare tale parametro nell'elenco dei parametri. Puoi controllare i nomi dei parametri di funzione usando il metodo descritto in questa risposta SO e genera un'eccezione se la funzione decorata non ha tale parametro.

Il parametro implicito o il parametro obbligatorio devono essere descritti nella docstring del decoratore ( custom_decorator nell'esempio). Se si utilizza @wraps decorator sulla funzione restituita ( wrapper nell'esempio), l'attributo __doc__ viene copiato dalla funzione f e sovrascrive qualsiasi docstring specificato per wrapper .

    
risposta data 28.12.2015 - 00:08
fonte

Leggi altre domande sui tag