我发现这个问答非常有趣,因为它为同一问题提供了几种不同的解决方案。我采用了所有这些函数并使用复杂的字典对象对其进行了测试。我不得不从测试中取出两个函数,因为它们有很多失败结果,并且它们不支持返回列表或字典作为值,我认为这是必不可少的,因为函数应该准备好any数据即将到来。
所以我通过 100.000 次迭代泵送其他函数timeit
模块和输出得出以下结果:
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)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
所有函数都有相同的针来搜索(“logging”)和相同的字典对象,其构造如下:
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]]
}
所有函数都提供相同的结果,但时间差异却很大!功能gen_dict_extract(k,o)
我的函数是从这里的函数改编而来的,实际上它很像find
来自 Alfe 的函数,主要区别在于,我正在检查给定对象是否具有 iteritems 函数,以防在递归期间传递字符串:
# python 2
def gen_dict_extract(key, var):
if hasattr(var,'iteritems'): # hasattr(var,'items') for python 3
for k, v in var.iteritems(): # var.items() for python 3
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
所以这个变体是这里最快、最安全的函数。和find_all_items
非常慢,而且距离第二慢还很远get_recursivley
而其余的,除了dict_extract
,彼此接近。功能fun
and keyHole
仅当您正在寻找字符串时才有效。
这里有有趣的学习方面:)