Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generator function behaves differently in various iteration contexts

Tags:

python-3.x

So I have this generator function for non-recursive permutations, when I use it in for loop, I get what I expect:

>>> for p in permutate3( "abc" ): print( p )
...
['a', 'b', 'c']
['a', 'c', 'b']
['b', 'a', 'c']
['b', 'c', 'a']
['c', 'a', 'b']
['c', 'b', 'a']

But once I use it in list or print with argument unpacking I get this strange output:

>>> list( permutate3( "abc" ) )
[['c', 'b', 'a'], ['c', 'b', 'a'], ['c', 'b', 'a'], ['c', 'b', 'a'], ['c', 'b', 'a'], ['c', 'b', 'a']]
>>> print( *permutate3( "abc" ) )
['c', 'b', 'a'] ['c', 'b', 'a'] ['c', 'b', 'a'] ['c', 'b', 'a'] ['c', 'b', 'a'] ['c', 'b', 'a']

Why does this happen?..

The function itself is:

def permutate3( s ):
    l = len( s )
    taken = [ False ] * l
    permutation = [ None ] * l
    current = 0
    stack = [ 0 ]

    while True:
        while stack[-1] < l:
            if not taken[ stack[-1] ]:
                permutation[current] = s[ stack[-1] ]
                if current == l-1:
                    yield permutation
                else:
                    taken[ stack[-1] ] = True
                    stack.append( 0 )
                    current+=1
                    break
            stack[-1]+=1
        else:
            stack.pop()
            if len( stack ) == 0:
                break
            else:
                current-=1
                taken[ stack[-1] ] = False
                stack[-1]+=1
                continue
like image 605
Vasyl Demianov Avatar asked Feb 25 '26 19:02

Vasyl Demianov


1 Answers

Dummy me. My function yields reference to the same object every time, which is changed by the function for subsequent permutations. Obviously it should be yield list( permutation ).

like image 61
Vasyl Demianov Avatar answered Mar 01 '26 14:03

Vasyl Demianov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!