Как правило, более "Pythonic" использовать утки; т. е. просто попробуйте найти цель, а не isinstance
. См. В чем различия между типом () и isinstance ()?
Тем не менее, ваша потребность в рекурсии требует повторного ввода значений словарей и элементов списка. (Вы также хотите найти ключи словарей?)
Оператор in
может использоваться как для строк, списков, так и словарей, поэтому нет необходимости отделять словари от списков при тестировании на членство. Предполагая, что вы не хотите проверять целевой объект как подстроку, используйте isinstance(basestring)
для предыдущей ссылки. Чтобы проверить, находится ли ваша цель среди значений словаря, проверьте членство в your_dictionary.values()
. См. Получить ключ по значению в словаре
Поскольку значения словаря могут быть списками или словарями, я все же могу проверять словарь и типы списков, как вы, но я упоминаю, что вы можете покрывать как элементы списка, так и ключи словаря одним оператором, потому что вы спрашиваете о том, чтобы быть Pythonic. и использование перегруженного oeprator типа in
для двух типов типично для Python.
Ваша идея использовать рекурсию необходима, но я бы не стал определять функцию с именем find
, потому что это встроенный Python, который вы (вроде) затеняете и делаете рекурсивный вызов менее читаемым, потому что другой программист может ошибочно подумать, что вы вызываете встроенную функцию (и в качестве хорошей практики вам может потребоваться оставить обычный доступ к встроенной программе на случай, если вы захотите вызвать ее).
Чтобы проверить числовые типы, используйте `numbers.Number ', как описано в Как проверить, является ли мой объект python числом?
Также, есть решение вашей проблемы в https://gist.github.com/douglasmiranda/5127251. Я обнаружил это перед публикацией, потому что предложение регулярного выражения ColdSpeed в комментарии заставило меня задуматься, не уводил ли я вас по неверному пути.
Так что-то вроде
import numbers
def recursively_search(object_from_json, target):
if isinstance(object_from_json, (basestring, numbers.Number)):
return object_from_json==target # the recursion base cases
elif isinstance(object_from_json, list):
for element in list:
if recursively_search(element, target):
return True # quit at first match
elif isinstance(object_from_json, dict):
if target in object_from_json:
return True # among the keys
else:
for value in object_from_json.values():
if recursively_search(value, target):
return True # quit upon finding first match
else:
print ("recursively_search() did not anticipate type ",type(object_from_json))
return False
return False # no match found among the list elements, dict keys, nor dict values