#python #recursion
#python #рекурсия
Вопрос:
Позвольте мне объяснить, показав вам проблемный код и его соответствующий вывод:
def find_amount_of(victim, key, value):
def eval(v, k, dir, sc):
hits = 0
print("{}: {} -> {}".format(dir, k, v))
# Currently only triggers when both have been hit
if k == key or k == None:
if v == value:
hits = 1
if type(v) == list or type(v) == dict:
hits = second(k, v, hits, dir, sc)
return hits
def second(name, vv, hits, dir, sc):
# Setup vars
sc = 1
hc = hits
if name != "":
dir.append(name)
# Decide treatment of vv
if type(vv) == dict:
for k, v in vv.items():
print("Second Counter: " str(sc) ", " str(dir))
hc = eval(v, k, dir, sc)
elif type(vv) == list:
for v in vv:
hc = eval(v, None, dir, sc)
# Return hits throughout entire thing
return hc
return second("", victim, 0, [], 0)
ex3 = {
"1": {
"1.1": 1
},
"2": {
"2.1": 2
}
}
print(find_amount_of(ex3, "1.3", 2))
Вывод:
Second Counter: 1, []
[]: 1 -> {'1.1': 1}
Second Counter: 2, ['1']
['1']: 1.1 -> 1
Second Counter: 1, ['1']
['1']: 2 -> {'2.1': 2}
Second Counter: 2, ['1', '2']
['1', '2']: 2.1 -> 2
0
Чего я не понимаю, так это почему dir изменился в первом экземпляре второго вызова функции (извините за мое ужасное название, это была просто быстрая тестовая функция, которую я сделал).
Когда вы смотрите на вывод, вы можете увидеть строку «Второй счетчик: 1, []». Это первый экземпляр, а dir — это просто список emtpy.
Теперь, чуть позже, строка «Второй счетчик: 1, [‘1’]» вызывает меня. Это все еще первый экземпляр, но по какой-то причине dir изменился.
Мой первый вопрос: почему он меняется, когда функция eval не изменяет вторую функцию, которая его вызвала?
Мой второй вопрос: как я могу это исправить? Нужен ли мне совершенно другой подход?
Прямо сейчас целью этого кода является перебор dicts и списков, чтобы всегда отслеживать, где именно он находится.
Комментарии:
1. Да, разберитесь с вашими именами, чтобы не использовать встроенные модули. dir всегда ссылается на один и тот же экземпляр списка, который можно изменить, добавив второй.
Ответ №1:
Я понял это.
Ответ на первый вопрос «Почему?» заключается в том, что python передает списки по ссылке, а не по значению.
Ответ на второй вопрос «Как исправить?» заключается в том, чтобы просто передать копию списка вместо фактического списка, например:
second(k, v, hits, dir.copy(), sc)
вместо этого:
second(k, v, hits, dir, sc)