Based of this answer, voglio creare un one line tree come parte di un'altra classe, come in tal modo:Una linea implementazione albero
self._tree = collections.defaultdict(lambda: self._tree)
ho bisogno di consentire agli utenti di detta classe di aggiungere elementi di percorso per l'albero ed eseguire alcuni callback a partire dal livello più basso dell'albero. La mia implementazione ingenuo solleva un errore quando ho eseguito pytest
:
def _add(self, tree, path):
for node in path:
tree = tree[node]
def _run(self, tree, callback):
for key in tree.keys():
callback(tree[key]) # !!! Recursion detected (same locals & position)
self._run(key)
Questo codice funziona se e solo se l'albero è definito come
def tree():
return collections.defaultdict(tree)
self._tree = tree()
Perché il mio approccio ingenuo non funziona con l'espressione lambda?
⚠ Il Zen of Python afferma che
Semplice è meglio che complesso.
Il lambda a una riga rende complesso il codice in cui è presente uno simpler implementation. Pertanto la lambda a una linea non deve essere utilizzata nel codice di produzione. Tuttavia, lascerò questa domanda qui per interesse accademico.
Il metodo passato a 'defaultdict' deve creare una nuova istanza, non fare riferimento a un oggetto esistente. Nel tuo caso 'tree' è un metodo che restituisce un nuovo' defaultdict (tree) ', ma il tuo one-liner è un lambda che restituisce l'istanza originale' self._tree' di 'defaultdict (lambda: ecc.)' – PaulMcG
@ PaulMcGuire: Allora perché 'd = collections.defaultdict (lambda: d); d ['foo'] ['bar'] 'sembra funzionare bene nonostante sia brutto quando stampato? – Sardathrion
La risposta di Kevin e il commento di Tadhg McDonald-Jensen illustrano l'impropria ricorsione nell'approccio lambda a una riga. – PaulMcG