Penso che questo sia un esempio leggermente ingannevole; c'è qualcosa che non hai dichiarato. Immagino che quando dici "hai un'interfaccia", ciò che intendi è che hai un codice che accetta un oggetto e chiama il suo metodo run
.
Se non si esegue il test del tipo di tale oggetto prima di chiamare il suo metodo run
, si sta utilizzando la digitazione anatra, semplice e semplice! (In questo caso, se ha un metodo run
, allora è un Runner
.) Finché non usi type
o isinstance
sull'oggetto con un metodo run
, allora sei Pythonic.
La domanda se accettare stringhe semplici o solo oggetti nodo è una domanda leggermente diversa. Le stringhe e gli oggetti node
probabilmente non implementano affatto la stessa interfaccia! Le stringhe fondamentalmente non sono ciarlatano come un node
, quindi non è necessario trattarle come se fossero una. Questo è come un elefante che arriva, e se vuoi che cova come un'anatra, devi dare all'elefante un registratore e addestrare l'elefante a usarlo prima.
Quindi non si tratta più di "digitazione anatra", ma del design dell'interfaccia. Stai cercando di decidere quanto vuoi che la tua interfaccia sia severa.
Per dare una risposta, quindi, a questo livello, penso che sia più Pythonic a supporre che run
restituisca un oggetto node
. Non è necessario utilizzare isinstance
o type
per verificarlo. Fai finta che sia un oggetto node
e se il programmatore che usa la tua interfaccia si sbaglia e vede un'eccezione, allora dovranno leggere la tua docstring, che dirà loro che run
deve passare un oggetto node
.
Quindi, se si si desidera che accetti anche le stringhe o le cose che smettono di funzionare come stringhe, è possibile farlo. E poiché le stringhe sono tipi piuttosto primitivi, direi che non è inappropriato utilizzare isinstance(obj, basestring)
(ma nontype(obj) == str
perché rifiuta le stringhe unicode, ecc.). Essenzialmente, sei un tipo molto liberale e gentile con gli utenti pigri del tuo programma; stai già andando oltre e accettando gli elefanti e le cose che fanno schifo come le anatre.
(Più concretamente, direi che questo è un po 'come chiamare iter
su un argomento all'inizio di una funzione che si desidera accettare entrambi i generatori e le sequenze.)
Sono un po 'confuso. Stai parlando del valore passato a 'run' (tramite' arg')? O stai parlando di come gestire il valore ipotetico restituito dal metodo 'run' di un oggetto che implementa l'interfaccia' Runner'? – senderle
Intendo il ritorno. Ho modificato il 'arg' in modo da non distrarre (grazie per averlo indicato). – Owen