Permettetemi innanzitutto di riconoscere che quello che voglio fare può essere considerato qualsiasi cosa da sciocco a cattivo, ma voglio scoprire se posso farlo comunque in Python.Come può un decoratore passare le variabili in una funzione senza cambiarne la firma?
Diciamo che ho un decoratore di funzioni che accetta gli argomenti delle parole chiave che definiscono le variabili e voglio accedere a quelle variabili nella funzione di avvolgimento. Potrei fare qualcosa di simile:
def more_vars(**extras):
def wrapper(f):
@wraps(f)
def wrapped(*args, **kwargs):
return f(extras, *args, **kwargs)
return wrapped
return wrapper
Ora posso fare qualcosa di simile:
@more_vars(a='hello', b='world')
def test(deco_vars, x, y):
print(deco_vars['a'], deco_vars['b'])
print(x, y)
test(1, 2)
# Output:
# hello world
# 1 2
La cosa che non mi piace di questo è che quando si utilizza questo decoratore, è necessario cambia la firma della chiamata della funzione, aggiungendo la variabile extra oltre allo schiaffo sul decoratore. Inoltre, se si guarda al l'aiuto per la funzione, si vede una variabile in più che non ci si aspetta di utilizzare quando si chiama la funzione:
help(test)
# Output:
# Help on function test in module __main__:
#
# test(deco_vars, x, y)
Questo lo fa apparire come l'utente deve chiamare la funzione con 3 parametri, ma ovviamente non funzionerà. Quindi dovresti anche aggiungere un messaggio alla docstring che indica che il primo parametro non fa parte dell'interfaccia, è solo un dettaglio di implementazione e dovrebbe essere ignorato. Questo è un po 'schifoso, però. C'è un modo per farlo senza appendere queste variabili su qualcosa nella portata globale? Idealmente, mi piacerebbe farlo sembrare come il seguente:
@more_vars(a='hello', b='world')
def test(x, y):
print(a, b)
print(x, y)
test(1, 2)
# Output:
# hello world
# 1 2
help(test)
# Output:
# Help on function test in module __main__:
#
# test(x, y)
io sono contento di un Python 3 unica soluzione se ne esiste uno.
Forse dovresti descrivere di più la tua necessità. Avrai solo una possibilità di decorare la funzione, quindi qual è il vantaggio di mettere 'a = 'hello'' nel decoratore, invece di metterlo come prima riga della funzione? –
Sembra che tu stia chiedendo come inserire "extra" nel test di chiusura dopo che è già stato compilato, senza dover modificare in alcun modo la definizione di "test". Se è così, non penso che sarà possibile senza alcuni terribili hack. – abarnert
Ma usando una macro [MacroPy] (https://github.com/lihaoyi/macropy) invece di un decoratore, immagino che sarebbe facile ... Sarebbe una risposta accettabile? – abarnert