1

I am seeing something in Python that I've never seen before.

I was working on a dynamic programming tutorial to find the longest common subsequence between two strings. To clarify I don't want help with that problem. My problem is that the parameter accs is storing the return values of previous function calls.

Here is the code:

def lcs(str1 = '', str2 = '', accs = []):
    if str1 and str2:
        str1 = list(str1)
        str2 = list(str2)
        for char1 in str1:
            for char2 in str2:
                if char1 == char2:
                    accs.append(char1)
                    str1.remove(char1)
                    str2.remove(char2)
                    return lcs(''.join(str1), ''.join(str2), accs=accs)
        str1.remove(char1)
        return lcs(''.join(str1), ''.join(str2), accs)
                
    else:
        return accs

print(lcs('AGGTAB','GXTXAYB'))
print(lcs('ABCDGH','AEDFHR'))

the print statements return

['A', 'G', 'T', 'B']
['A', 'G', 'T', 'B', 'A', 'D', 'H']

The first print statement is correct, but the second includes the substring from the first.

when I run the function lcs (no parens) in a cell below the code above without calling it I get the following:

<function __main__.lcs(str1='', str2='', accs=['A', 'G', 'T', 'B', 'A', 'D', 'H', 'A', 'D', 'H'])>

I've tried running the code in cells in Jupyter-lab and then by running it as a script in VSCode and from the command line and the values seem to accumulate in the parameter in both. What is happening here?

Running Python 3.8.5 in Ubuntu under WSL2 and Python 3.9.1 on Windows. The problem is similar in both places.

  • 1
    Does this - https://stackoverflow.com/questions/41686829/warning-about-mutable-default-argument-in-pycharm answer your questions? – Daniel Hao Dec 22 '20 at 03:41
  • @Daniel Hao posted a good link, you can also look here for an explanation: https://docs.python-guide.org/writing/gotchas/ – jdaz Dec 22 '20 at 03:43

2 Answers2

1

You should assign an empty list for the variable accs before the next function call. When you not clear that accs value, the second function call takes the first function call's accs value as a parameter.

print(lcs('AGGTAB','GXTXAYB'))
print(lcs('ABCDGH','AEDFHR', []))
Hasee Amarathunga
  • 1,901
  • 12
  • 17
1

@xjoshbrownx - this is one of the well-known common gotchas, you can also find info. here - https://docs.python-guide.org/writing/gotchas/

Daniel Hao
  • 4,922
  • 3
  • 10
  • 23