Un controllo esplicito della capacità del callback di gestire i parametri è il migliore che riuscirai a fare. Python potrebbe essere loosie-goosie nella sua digitazione anatra, ma si lamenterà e genererà un'eccezione TypeError
se si alimenta una funzione con il numero sbagliato di parametri. Nessun ifs, ands o buts.
Hai funzioni esistenti nel campo che non ritieni di poter cambiare - e probabilmente per una buona ragione. Quindi, avendo un'ispezione che chiede "cosa può accettare questa funzione di callback?" o "cosa si aspetta questa funzione di callback?" - potrebbe essere inelegante, ma questo è ciò che è a tua disposizione.
Le altre scelte riguardano:
-
Avere qualche forma di stato relativo all'oggetto (come un valore o metodo di istanza aggiuntivo) o anche uno stato globale (che sia una vera variabile globale, una variabile di classe, un oggetto di segnalazione singleton o whathaveyou) quali callback possono riferimento per ottenere le informazioni estese che stai ora offrendo loro. Ecco come C, Unix e molte altre codebase gestiscono informazioni eccezionali e aggiuntive. Sfortunatamente non è particolarmente elegante e può essere piuttosto problematico / non lavorativo per le applicazioni con multithreading.
-
Nella remota possibilità che il tuo parametro data
sia un tipo estensibile, potresti essere in grado di aggiungere campi ad esso. Se è un dict
o una struttura simile, sei d'oro, purché le callback suonino secondo le regole di digitazione anatra e non controlli rigorosamente che abbiano ottenuto solo i campi che si aspettavano. Questo è un trucco che spesso funziona in linguaggi dinamici, anche se cadrebbe piatto sul suo volto in linguaggi tipizzati staticamente / ambienti che passano dati. Ma devi essere fortunato ad avere questo lavoro. Se data
è un tipo più statico, torni alla scelta 1 o al tuo approccio basato sull'ispezione ("scelta 0").
Aggiorna
Per inciso, il tuo codice funzionerà correttamente in Python 2. Ma Python 3 cambia la posizione in cui è memorizzato il codice. Per comprendere sia il tuo attuale Python 2 che le future mosse su Python 3, ecco uno shim che funziona in entrambi:
import sys
_PY2 = sys.version_info[0] == 2
def arg_count(f):
code = f.func_code if _PY2 else f.__code__
return code.co_argcount
Quindi:
if arg_count(self._callback) > 1:
....