bremen_matt
bremen_matt

Reputation: 7349

Python generator to list

I have a Python generator lexg which produces a list at each iteration. The code seems to work in the traditional for-loop sense, that is,

for i in lexg(2,2): print(i)

produces:

[2, 0]
[1, 1]
[1, 0]
[0, 2]
[0, 1]
[0, 0]

but seems to break in list comprehension, that is, both

list(lexg(2,2))

and

[i for i in lexg(2,2)]

produce

[[0, 0], 
 [0, 0], 
 [0, 0], 
 [0, 0], 
 [0, 0], 
 [0, 0]]

whereas, I expect list(lexg(2,2)) to produce

[[2, 0]
 [1, 1]
 [1, 0]
 [0, 2]
 [0, 1]
 [0, 0]]

The code for lexg is:

def lexg( n, d ):
    exponent    = [0] * n;
    def looper( m, totalDegree ):    
        r   = reversed( range( 0, d - totalDegree + 1 ) );
        for j in r:
            exponent[n-m] = j;
            if m == 1: 
                yield exponent;
            else: 
                for x in looper( m-1, totalDegree+j ): yield x
    return looper( n, 0 );

What is causing the empty output?

Edit/Solution

The problem, as suggested below, is the fact that the same list is returned at every step of the generator. One solution is therefore to copy the list before returning. For example, I have changed the yield exponent; line of lexg to yield list(exponent);, which resolves the problem.

Upvotes: 1

Views: 208

Answers (1)

DAXaholic
DAXaholic

Reputation: 35358

As pointed out by deceze you essentially end up with a list of lists pointing to the same instance

To make it more clear, try that

a = list(lexg(2,2))
a[0][0] = 3
print(a)

which results in

[[3, 0], [3, 0], [3, 0], [3, 0], [3, 0], [3, 0]]

Upvotes: 4

Related Questions