Почему этот код DFS работает только при вызове его внутри генератора?

#python #generator #depth-first-search

#python #генератор #поиск в глубину

Вопрос:

Я был бы действительно признателен за вашу помощь. Я изучаю пути к DFS и понимаю код, но чего я не понимаю, так это последней строки. Почему я не могу просто вызвать функцию как dfs_paths(graph, ‘A’, ‘F’), а не list (dfs_paths(graph, ‘A’, ‘F’)), чтобы приведенный ниже код работал? Спасибо.

 graph = {'A': set(['B', 'C']),
         'B': set(['A', 'D', 'E']),
         'C': set(['A', 'F']),
         'D': set(['B']),
         'E': set(['B', 'F']),
         'F': set(['C', 'E'])}

def dfs_paths(graph, start, goal):
    stack = [(start, [start])]
    while stack:
        (vertex, path) = stack.pop()
        for next in graph[vertex] - set(path):
            if next == goal:
                yield path   [next]
            else:
                stack.append((next, path   [next]))

dfs_paths(graph, 'A', 'F')
  

Ответ №1:

Потому что dfs_paths это не обычная функция; это функция генератора. Когда вы запускаете функцию, она возвращает только генератор и фактически не выполняет какой-либо код в теле, пока вы не начнете перебирать возвращаемое значение. Эта итерация может быть явной с помощью for цикла:

 for path in dfs_paths(graph, 'A', 'F'):
    ...
  

или неявный через функцию типа list , которая использует итератор:

 paths = list(dfs_paths(graph, 'A', 'F'))
  

Ответ №2:

Это оператор yield в функции.

Методы с yield в них являются генераторами. Генераторы возвращают итератор при вызове. Если вы хотите получить полное возвращаемое значение (весь путь), вы должны завершить итерацию по итератору. Отсюда необходимость в list() — который неявно выполняет итерацию по итератору, предоставляя вам весь путь.