Why it seems contradictory when yield meet recursion in python?

Question:

I tried to implement full permutation via python generator & recursion, but the output from ‘print’ is different from any other form of generator utility.

def gen_perms(seq):
    seq_len = len(seq)
    def swap(i,j):
        x = seq[i]
        seq[i] = seq[j]
        seq[j] = x
    def perms(n):
        if n == seq_len - 1:
            yield seq
        for i in range(seq_len - n):
            swap(n, n + i)
            yield from perms(n + 1)
            swap(n, n + i)
    yield from perms(0)

print('output1:')
for i in gen_perms([1,2,3]):
    print(i, end=', ')
print('')
print('output2:')
print('list(perm):', list(gen_perms([1,2,3])))

print('output3:')
it2 = (p for p in gen_perms([1,2,3]))
print(it2)
print(list(it2))

print('output4:')
def it3():
    for p in gen_perms([1,2,3]):
        yield p
print(list(it3()))

And the output was:

output1:
[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 2, 1], [3, 1, 2], 
output2:
list(perm): [[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
output3:
<generator object <genexpr> at 0x0000021E895EB3C0>
[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
output4:
[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
Asked By: Blandying

||

Answers:

The result from output 1 is seen as correct because you print each yield before the next.

The others are not correct because you save each yield and print them all later. The reason is that you have yield seq and seq is mutated later.

It may be better to have: yield seq[:]

See this article about python names.

Answered By: quamrana