Python Forum

Full Version: yield question with append
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
when I try to use print the output the yield result, everything is shown as expected. The code and output is as below:
def triangles():
    oo = [1] 
    yield oo 
    oo.append(1)
    yield oo  
    oo.append(1)
    yield oo 
    oo.append(1)
    yield oo 

# Collect the first 3 rows of Triangle
n = 0
for t in triangles():
    print (t)
    n += 1
    if n == 3:  
        break
the output is:
Output:
[1] [1, 1] [1, 1, 1]
However when I tried to append the yield result further, like below
n = 0
results = []
for t in triangles():
    ## print (t)
    results.append(t)
    n += 1
    if n == 3:  
        break

# Print the results
for t in results:
    print(t)
the output becomes:
Output:
[1, 1, 1] [1, 1, 1] [1, 1, 1]
Actually it is hard for me to understand the result. why the 1st and 2nd row changes after further appending?
triangles returns the same list each time. Look at it this way:
def triangles():
    oo = [1]
    yield oo
    oo.append(1)
    yield oo
    oo.append(1)
    yield oo
    oo.append(1)
    yield oo


# Collect the first 3 rows of Triangle
saved_triangles = []
for t in triangles():
    saved_triangles.append(t)
    print(t, id(t))
print("\nSaved Triangles")
for t in saved_triangles:
    print(t, id(t))
Output:
[1] 2446984510720 [1, 1] 2446984510720 [1, 1, 1] 2446984510720 [1, 1, 1, 1] 2446984510720 Saved Triangles [1, 1, 1, 1] 2446984510720 [1, 1, 1, 1] 2446984510720 [1, 1, 1, 1] 2446984510720 [1, 1, 1, 1] 2446984510720
As you can see from the output, the object returned by triangles() is always the same list (the id's match). The first time triangles() yields a list, the list contains [1]. The second yield returns the same list, but now the list contains [1, 1]. Printing the saved_triangles show that the first list yielded by triangles() magically morphed from containing [1] to containing [1, 1].

I think you want triangles to return a new list for each yield.
def triangles(count):
    for i in range(count):
        yield [1] * (i + 1)


# Collect the first 3 rows of Triangle
saved_triangles = []
for t in triangles(4):
    saved_triangles.append(t)
    print(t, id(t))
print("\nSaved Triangles")
for t in saved_triangles:
    print(t, id(t))
Output:
[1] 2280964861568 [1, 1] 2280964456128 [1, 1, 1] 2280964455616 [1, 1, 1, 1] 2280964886848 Saved Triangles [1] 2280964861568 [1, 1] 2280964456128 [1, 1, 1] 2280964455616 [1, 1, 1, 1] 2280964886848
Now triangles yields a new list each time. Yielding a longer list doesn't change the length of previous yielded lists.
Appreciate it, deanhystad: I understand it. the id helps.