В некоторых случаях может быть предпочтительнее использовать стек вместо рекурсии для генераторов. Должна быть возможность переписать рекурсивный метод, используя стек и цикл while.
Вот пример рекурсивного метода, который использует обратный вызов и может быть переписан с использованием логики стека:
def traverse_tree(callback):
# Get the root node from somewhere.
root = get_root_node()
def recurse(node):
callback(node)
for child in node.get('children', []):
recurse(child)
recurse(root)
Приведенный выше метод перебирает дерево узлов, где каждый узел имеет массив children
, который может содержать дочерние узлы. При обнаружении каждого узла вызывается обратный вызов и ему передается текущий узел.
Метод можно использовать таким образом, распечатывая некоторые свойства на каждом узле.
def callback(node):
print(node['id'])
traverse_tree(callback)
Вместо этого используйте стек и напишите метод обхода в качестве генератора
# A stack-based alternative to the traverse_tree method above.
def iternodes():
stack = [get_root_node()]
while stack:
node = stack.pop()
yield node
for child in reversed(node.get('children', [])):
stack.append(child)
(Обратите внимание, что если вы хотите использовать тот же порядок обхода, что и вначале, вам нужно изменить порядок дочерних элементов, потому что первый дочерний элемент, добавленный в стек, будет последним извлеченным.)
Теперь вы можете получить то же поведение, что и traverse_tree
выше, но с генератором:
for node in iternodes():
print(node['id'])
Это не универсальное решение, но для некоторых генераторов вы можете получить хороший результат, заменив обработку стека на рекурсию.