python - defaultdict of defaultdict, nested




recursion (3)

C'è un modo per fare di default anche l'impostazione predefinita per defaultdict? IOW, se lo faccio:

x = defaultdict(...stuff...)
x[0][1][0]
{}

È quello che voglio. Probabilmente finirò per usare il modello di mazzo, ma quando ho capito che non sapevo come farlo, mi ha interessato.

Quindi, posso fare:

x = defaultdict(defaultdict)

ma questo è solo un livello:

x[0]
{}
x[0][0]
KeyError: 0

Ci sono ricette che possono farlo. Ma può essere fatto semplicemente usando i normali argomenti defaultdict?

Nota che qualcuno lo ha contrassegnato come un duplicato di Python: defaultdict of defaultdict? , ma questa non è la stessa domanda ... quella domanda era come fare un defaultdict a due livelli; questo è come fare un defaultdict ricorsivo a livello infinito.


C'è un trucco elegante per farlo:

tree = lambda: defaultdict(tree)

Quindi puoi creare la tua x con x = tree() .


Le altre risposte qui ti dicono come creare un defaultdict che contiene "infinitamente molti" defaultdict , ma non riescono ad affrontare quello che penso possa essere stato il tuo bisogno iniziale, che era semplicemente avere un defaultedict a due profondità.

Forse stavi cercando:

defaultdict(lambda: defaultdict(dict))

I motivi per cui potresti preferire questo costrutto sono:

  • È più esplicito della soluzione ricorsiva e quindi probabilmente più comprensibile per il lettore.
  • Ciò consente alla "foglia" di defaultdict di essere qualcosa di diverso da un dizionario, ad esempio: defaultdict(lambda: defaultdict(list)) o defaultdict(lambda: defaultdict(set))

Simile alla soluzione di BrenBarn, ma non contiene il nome dell'albero delle variabili due volte, quindi funziona anche dopo le modifiche al dizionario delle variabili:

tree = (lambda f: f(f))(lambda a: (lambda: defaultdict(a(a))))

Quindi puoi creare ogni nuova x con x = tree() .

Per la versione def , possiamo usare l'ambito di chiusura della funzione per proteggere la struttura dati dalla falla in cui le istanze esistenti smettono di funzionare se il nome tree è in estensione. Sembra questo:

from collections import defaultdict

def tree():
    def the_tree():
        return defaultdict(the_tree)
    return the_tree()






defaultdict