Ваш код работает неправильно, потому что вы return
получаете результаты каждого рекурсивного вызова, даже если он не нашел искомый ключ и не внес изменений. Когда ваша функция достигает недопустимого объекта в первый раз (например, внутренний вызов выполняется с недиктивным значением), она возвращает None
(по умолчанию), и это распространяется по стеку вызовов, чтобы стать окончательным результатом top- вызов уровня тоже.
Поскольку вы изменяете словарь на месте, вам действительно не следует использовать return
для значения словаря. У вызывающей стороны уже есть ссылка на диктовку, над которой вы работаете, поэтому вы можете вместо этого использовать возвращаемое значение, чтобы сообщить, когда вместо этого мы нашли нужный ключ:
def remove_a_key(d, remove_key):
if isinstance(d, dict) and d:
for key in list(d.keys()):
if key == remove_key:
del d[key]
return True # first base case, we found the key
else: # recursive case
if remove_a_key(d[key], remove_key): # only return if we were successfull
if not d[key]: # empty dict cleanup code
del d[key]
return True
return False # third base case, failure
Примечание. Я переместил немного кода, который удалил пустые словари, чтобы быть в рекурсивном регистре. Это предполагает, что у вас нет пустых словарей, которые вы ожидаете очистить в начале, вы просто не хотите, чтобы удаление последней листовой записи в дикте оставляло кучу потерянных родительских словарей вокруг.
Назовите код следующим образом:
nested = {
"a": {"aa": 1, "ab": 2},
"b": {"ba": 3, "bb": 4},
}
print(nested) # prints {'a': {'aa': 1, 'ab': 2}, 'b': {'ba': 3, 'bb': 4}}
remove_a_key(nested, "bb")
print(nested) # prints {'a': {'aa': 1, 'ab': 2}, 'b': {'ba': 3}}
remove_a_key(nested, "ba")
print(nested) # prints {'a': {'aa': 1, 'ab': 2}}
Последнее замечание: этот код удаляет не более одного ключа. Если вы хотите, чтобы он удалял все вхождения ключа, которые могут появляться несколько раз, вам нужно избавиться от return
в рекурсивном случае. На самом деле, вам даже не нужно будет возиться с возвращаемыми значениями вообще в этой ситуации, вы просто будете всегда проверять весь текст безоговорочно.