2

I have a tree from which I want to return its children as a list through a function. In this function, I needed to iterate over a list of strings. At first I did it by using the inline for loop

    def get_children(root):
        
        Data = [ ]
        Data.append( root.data )
        
        for child in root.children:
              Data.append( elem for elem in get_children(child) )
        return Data

However, I got the following strange result:

['Electronics', <generator object get_children.<locals>.<genexpr> at 0x7fb3a081a3c0>, <generator object get_children.<locals>.<genexpr> at 0x7fb3a081a7b0>, <generator object get_children.<locals>.<genexpr> at 0x7fb3a081a9e0>]

Then, I changed the inline for loop into a typical one and the problem is resolved, i.e.,

   for elem in get_children(child):
        Data.append( elem )

I was wondering if you could help me understand why this happened. I've read a similar post about list comprehension, however, I'm still confused trying to understand the difference here.

Atalajaka
  • 125
  • 1
  • 2
  • 14
BoofKoor
  • 59
  • 2
  • See https://stackoverflow.com/questions/47789/generator-expressions-vs-list-comprehensions – Tom Dalton Feb 28 '22 at 15:29
  • There's no such thing as an "inline for loop". What you have is a generator expression, which produces an object that can be iterated over lazily. – chepner Feb 28 '22 at 15:41
  • If anything, you would want `Data.append(elem) for elem in get_children(child)` anyway (but that's not going to do what you think it would). Just use `Data.extend(get_children(child))`. – chepner Feb 28 '22 at 15:42
  • I dont know why but i am getting an `no attribute` error at `data.append(root.data)` and aswell as on for child in `root.children` – Faraaz Kurawle Feb 28 '22 at 15:49
  • I dont know why but i am getting an `no attribute` error at `data.append(root.data)` and aswell as on for child in `root.children` – Faraaz Kurawle Feb 28 '22 at 15:49

3 Answers3

3

Because you didn't wrap your list comprehension with [], the return value of it is a generator expression (which generates the list you made). You can fix this by simply wrapping the expression with []

yair koskas
  • 134
  • 5
  • Thank you! It resolved the issue but it does not give the desired result. In fact it returns a list of lists instead of a list. So, the result is still different with that of the typical for loop. – BoofKoor Feb 28 '22 at 15:41
  • @BoofKoor , see this https://stackoverflow.com/questions/952914/how-to-make-a-flat-list-out-of-a-list-of-lists – Faraaz Kurawle Feb 28 '22 at 20:04
2

you used Generator expressions instead of list comprehension Generator Expressions are somewhat similar to list comprehensions, but the former doesn’t construct list object. Instead of creating a list and keeping the whole sequence in the memory the generator generates the next element in demand.

shoam
  • 155
  • 7
1

The problem is here at Data.append( elem for elem in get_children(child)), you haven't wrapped the list comprehension. So the solution is Data.append([elem for elem in get_children(child)]) to just add [ at start and ] at end of list comprehension.

I think yo are trying to get all child of the root, well here's solution from Getting every child widget of a Tkinter window

root.winfo_children()

You can use this instead of for-loop, as this would provide you with every children of root window.

Faraaz Kurawle
  • 1,085
  • 6
  • 24