Я знайшов це запитання дуже цікавим, оскільки воно пропонує кілька різних рішень для однієї і тієї ж проблеми. Я взяв усі ці функції і протестував їх за допомогою складного об'єкта словника. Мені довелося вилучити дві функції з тесту, оскільки їм довелося багато невдалих результатів, і вони не підтримували повернення списків або диктів як значень, що я вважаю суттєвим, оскільки функція повинна бути підготовлена майже до будь-яких даних.
Отже, я прокачав інші функції через 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)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Усі функції мали однакову стрілку для пошуку ('ведення журналу') та однаковий об'єкт словника, який побудований так:
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, на випадок, якщо рядки передаються під час рекурсії:
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
Отже, цей варіант є найшвидшим і найбезпечнішим із функцій тут. І find_all_items
неймовірно повільний і далеко другий найповільніший, get_recursivley
тоді як решта, крім dict_extract
, знаходиться близько один до одного. Функції fun
і keyHole
тільки працювати , якщо ви шукаєте рядки.
Цікавий аспект навчання тут :)