Проблема с печатью выражения генератора в виде списка

#python #list #binary-tree #generator

#питон #Список #двоичное дерево #генератор

Вопрос:

Я пытаюсь вернуть значения всех листьев в двоичном дереве с помощью генератора и поместить полученные значения в список. Это мой рекурсивный код, который использует операторы yield, но я не знаю, как вернуть конечные значения с помощью генератора. Второй фрагмент кода под названием «Предыдущий код» показывает тот же код с операторами печати, который выводит правильные значения, поэтому единственная проблема-генератор. Как примечание, этот код использует root.left и root.right импортированы из класса двоичного дерева и, похоже, работают правильно. Заранее благодарю вас за любую помощь!!

Мой код

 def leaves_list(self):  def find(root):  if not root:  yield  if not root.left and not root.right:  yield root.data  if root.left:  find(root.left)  if root.right:  find(root.right)  # my attempt  a = find(self.root)  lst = []  for i in a:  lst.append(next(a))  return find(self.root)  

Предыдущий Код

 def leaves_list(self):  def find(root):  if not root:  return  if not root.left and not root.right:  print(root.data, end = " ")  return  if root.left:  find(root.left)  if root.right:  find(root.right)  return find(self.root)  

Это мой код тестера, и он должен возвращать список [5, 1, 8, 4] .

Код тестера

 root = LinkedBinaryTree.Node(3) T = LinkedBinaryTree(root) a = LinkedBinaryTree.Node(2) a.parent = root root.left = a b = LinkedBinaryTree.Node(7) b.parent = root root.right = b c = LinkedBinaryTree.Node(9) c.parent = a a.left = c d = LinkedBinaryTree.Node(5) d.parent = c c.left = d e = LinkedBinaryTree.Node(1) e.parent = c c.right = e f = LinkedBinaryTree.Node(8) f.parent = b b.left = f g = LinkedBinaryTree.Node(4) g.parent = b b.right = g  print(T.leaves_list())  

Комментарии:

1. Это трудно отладить без классов дерева и узлов, но я бы заметил, что lst.append(next(a)) это должно быть lst.append(i) так, как есть, вы пропускаете все остальные значения.

2. Вы делаете это, чтобы попрактиковаться в генераторах, или вам просто интересно получить список? Потому что простая версия генератора неэффективна.

Ответ №1:

Есть несколько проблем с вашей попыткой:

  • find(self.root) вызывается дважды. В этом не должно быть необходимости, так как он выполнит работу дважды, чтобы снова получить тот же результат
  • lst создается и заполняется, но никогда не используется. Тебе, наверное, стоит его вернуть.
  • Не используйте итератор как с for циклом, так и с повторными вызовами next() . Когда вы делаете это, вы фактически переходите к следующему значению дважды на каждой итерации, тем самым пропуская значение в каждой итерации.
  • Учтите также, что стандартная list функция уже имеет эту функцию создания списка из итератора.
  • В find функции вы ничего не делаете со значениями, полученными рекурсивным вызовом. Вы также должны уступить им. Для этого вы можете использовать yield from синтаксис.
  • if not root не будет работать корректно, когда дерево действительно пустое, так как выполнение все еще продолжается после этого if блока, и поэтому возникнет исключение. Тебе нужно return туда.
  • Кроме того, когда дерево пустое, не должно быть ничего, что было бы получено. Итератору разрешено просто ничего не давать, что в этом случае уместно.
  • Это не проблема, но поскольку у вас есть if not root базовый вариант, вам действительно не нужно проверять None , прежде чем идти влево или вправо. Таким образом, эти if условия могут быть удалены, и рекурсивные вызовы могут выполняться безоговорочно.

Вот исправленная версия:

 def leaves_list(self):  def find(root):  if not root:  return  if not root.left and not root.right:  yield root.data  yield from find(root.left)  yield from find(root.right)   return list(find(self.root))  

Комментарии:

1. Этот комментарий может быть лучше помещен в вопрос, поскольку это тема Спрашивающего.

2. Я частично так и сделал, но затем увидел полный список вопросов вашего ответа и подумал, что он тоже может туда вписаться.

Ответ №2:

 # my attempt a = find(self.root) lst = [] for i in a:  lst.append(i) return lst  

Более короткая альтернатива:

 # my attempt return list(find(self.root))