Я вывел то, что получил во время каждой итерации generate_string, и это то, что я получил. Скорее всего, это сбивает с толку, потому что ничто не ведет себя так, как вы ожидали, но позвольте мне объяснить, что думает Python.
#1st time
current_string = ""
still_to_place = [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
Мы начинаем пропускание в приведенных выше данных, однако, как мы пройти через то, что происходит, мы первый поп первого массива ['a', 'b', 'c']
, и мы начинаем перебирать этот Popped массива. Однако, так как мы назвали .pop (0), теперь мы только последнюю часть массива, still_to_place.pop(0)
на первом рекурсивного вызова, который сделал для generate_string()
#2nd time
current_string = "a"
still_to_place = [['d', 'e', 'f'], ['g', 'h', 'i']]
Это именно то, что было в current_string и still_to_place при первом вызове рекурсивного вызова. Теперь мы начнем выполнение функции с самого начала. Мы снова вызываем функцию pop, удаляя второй массив ['d', 'e', 'f']
. Теперь мы остаемся только с третьим и последним массивом.
#3rd time
current_string = "ad"
still_to_place = [['g', 'h', 'i']]
Как мы перебираем ['g', 'h', 'i']
, потому что still_to_place теперь пуст. (Мы только что вытащили последний массив.) Любые вызовы generate_string перейдут непосредственно к предложению else, и мы собираемся распечатать строку «объявление» плюс значения в массиве, который мы только что выскочили.
#4th, 5th and 6th time
still_to_place = []
current_string = "adg"
still_to_place = []
current_string = "adh"
still_to_place = []
current_string = "adi"
Теперь мы продолжим, когда последний рекурсивный вызов прекратился, когда мы проходим второй раз. Здесь все запутывается. Когда мы остановились current_string = "a"
и still_to_place
было изначально [['d', 'e', 'f'], ['g', 'h', 'i']]
, но с тех пор мы вытащили все из массива. Видите ли, массивы ведут себя иначе, чем числа или строки. Все версии массива используют одни и те же данные. Вы меняете данные один раз, он меняет его везде, где используется массив. (объекты и словари также ведут себя таким образом.)
Итак, все, что сказал still_to_place = []
, и still_to_place
останутся пустыми для остальной части рекурсивных вызовов. Потенциальные_итуты все еще имеют данные, которые он вытащил из ['d', 'e', 'f']
. Мы уже выполнили «d» строка с шагом # 4, # 5 и # 6, так что мы можем закончить, где мы из
#7th and 8th times
still_to_place = []
current_string = "ae"
still_to_place = []
current_string = "af"
Еще раз potential_items имеет ['a', 'b', 'c']
и мы уже выполнили «а ». В отличие от still_to_place, потенциальные_имяты - это локальная переменная с меньшей областью. Если вы знаете, как работают области действия, то это будет сделано, потому что мы можем иметь несколько потенциальных_итем, но это то же самое, что и для_пользователя. Каждый раз, когда мы выталкивали элемент still_to_place, мы добавляли всплывающий результат к новой переменной потенциальных элементов с ограниченной областью. still_to_place был глобальным для всей программы, поэтому одно изменение на still_to_place приведет к изменениям, которые не ожидаются.
Надеюсь, я сделал вещи более запутанными и не менее запутанными. Оставьте комментарий о том, что вам нужно больше разъяснений.
О, мальчик! Спасибо за сплоченный ответ. Я доволен тем, что мое понимание рекурсии в порядке, но, похоже, мое понимание существования массива не было. Это решение, которое вы предлагаете так же, как и другой комментатор (передать срез массива, когда я иду дальше, а не изменять массив)? Тонны считывания о входящих ... –
Да, решение Hacoo было бы отличным способом решения этого вопроса. Когда вы нарезаете массив, данные копируются, предотвращая проблему, когда вы видите в коде. [Эта статья] (http://henry.precheur.org/python/copy_list) отлично справляется с объяснением того, что происходит с массивом. Кроме того, если вы можете щелкнуть стрелку над номером 0, чтобы повысить ответ, это было бы потрясающе. –