Ho trovato questa domanda / risposta molto interessante, poiché fornisce diverse soluzioni per lo stesso problema. Ho preso tutte queste funzioni e le ho testate con un complesso oggetto dizionario. Ho dovuto togliere due funzioni dal test, perché avevano molti risultati non riusciti e non supportavano la restituzione di elenchi o dettami come valori, cosa che trovo essenziale, poiché una funzione dovrebbe essere preparata per quasi tutti i dati a venire.
Quindi ho pompato le altre funzioni in 100.000 iterazioni attraverso il timeit
modulo e l'output è arrivato al seguente risultato:
0.11 usec/pass on gen_dict_extract(k,o)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6.03 usec/pass on find_all_items(k,o)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0.15 usec/pass on findkeys(k,o)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1.79 usec/pass on get_recursively(k,o)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0.14 usec/pass on find(k,o)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0.36 usec/pass on dict_extract(k,o)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Tutte le funzioni avevano lo stesso ago per la ricerca ('registrazione') e lo stesso oggetto dizionario, che è costruito in questo modo:
o = { 'temparature': '50',
'logging': {
'handlers': {
'console': {
'formatter': 'simple',
'class': 'logging.StreamHandler',
'stream': 'ext://sys.stdout',
'level': 'DEBUG'
}
},
'loggers': {
'simpleExample': {
'handlers': ['console'],
'propagate': 'no',
'level': 'INFO'
},
'root': {
'handlers': ['console'],
'level': 'DEBUG'
}
},
'version': '1',
'formatters': {
'simple': {
'datefmt': "'%Y-%m-%d %H:%M:%S'",
'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
}
}
},
'treatment': {'second': 5, 'last': 4, 'first': 4},
'treatment_plan': [[4, 5, 4], [4, 5, 4], [5, 5, 5]]
}
Tutte le funzioni hanno fornito lo stesso risultato, ma le differenze di orario sono notevoli! La funzione gen_dict_extract(k,o)
è la mia funzione adattata dalle funzioni qui, in realtà è più o meno come la find
funzione di Alfe, con la differenza principale, che sto controllando se l'oggetto dato ha la funzione iteritems, nel caso in cui le stringhe vengano passate durante la ricorsione:
def gen_dict_extract(key, var):
if hasattr(var,'iteritems'):
for k, v in var.iteritems():
if k == key:
yield v
if isinstance(v, dict):
for result in gen_dict_extract(key, v):
yield result
elif isinstance(v, list):
for d in v:
for result in gen_dict_extract(key, d):
yield result
Quindi questa variante è la più veloce e sicura delle funzioni qui. Ed find_all_items
è incredibilmente lento e lontano dal secondo più lento get_recursivley
mentre il resto, tranne dict_extract
, è vicino l'uno all'altro. Le funzioni fun
e funzionano keyHole
solo se stai cercando stringhe.
Aspetto interessante di apprendimento qui :)