bremen_matt bremen_matt - 3 months ago 13
Python Question

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.

Answer

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]]
Comments