J'ai trouvé ce Q / R très intéressant, car il fournit plusieurs solutions différentes pour le même problème. J'ai pris toutes ces fonctions et les ai testées avec un objet dictionnaire complexe. J'ai dû retirer deux fonctions du test, car elles avaient trop de résultats d'échec et elles ne prenaient pas en charge le renvoi de listes ou de dictionnaires en tant que valeurs, ce que je trouve essentiel, car une fonction doit être préparée pour presque toutes les données à venir.
J'ai donc pompé les autres fonctions en 100.000 itérations à travers le timeit
module et la sortie est arrivée au résultat suivant:
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)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Toutes les fonctions avaient la même aiguille à rechercher ('journalisation') et le même objet dictionnaire, qui est construit comme ceci:
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]]
}
Toutes les fonctions donnent le même résultat, mais les décalages horaires sont dramatiques! La fonction gen_dict_extract(k,o)
est ma fonction adaptée des fonctions ici, en fait, c'est un peu comme la find
fonction d'Alfe, avec la principale différence, que je vérifie si l'objet donné a une fonction iteritems, au cas où des chaînes seraient passées pendant la récursivité:
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
Cette variante est donc la plus rapide et la plus sûre des fonctions ici. Et find_all_items
est incroyablement lent et loin du deuxième plus lent get_recursivley
tandis que le reste, sauf dict_extract
, est proche l'un de l'autre. Les fonctions fun
et keyHole
ne fonctionnent que si vous recherchez des chaînes.
Aspect d'apprentissage intéressant ici :)