0

I wrote some code that found the fastest way of getting the sum of a number by adding numbers that were part of a list together ex: bestSum(3, [800, 1, 3]) would return [3] because that would be the best way of getting 3 (first number) with the numbers provided would be simply adding 3. Code:

def bestSum(target, lst, mochi = {}):
    if target in mochi:
        return mochi[target]

    if target == 0:
        return []
    if target < 0:
        return None

    shortestCombination = None

    for i in lst:
        remainderCombination = bestSum(target - i, lst, mochi)
        if remainderCombination is not None:
        remainderCombination = [*remainderCombination, i]
            if shortestCombination is None or len(remainderCombination) < len(shortestCombination):
                shortestCombination = remainderCombination

    mochi[target] = shortestCombination

    return shortestCombination

I ran into this issue where data would be saved between times I ran the code, for example if I run just

print(bestSum(8, [4])

It Returns

[4, 4]

However if I run

print(bestSum(8, [2, 3, 5]))
print(bestSum(8, [4]))

it returns:

[5, 3]
[5, 3]

Am I doing something wrong here? Is this potentially a security vulnerability? Is there a way to make this return correctly? What would cause python to do something like this?

some1and2
  • 41
  • 3
  • 1
    Does this answer your question? [Why is the empty dictionary a dangerous default value in Python?](https://stackoverflow.com/questions/26320899/why-is-the-empty-dictionary-a-dangerous-default-value-in-python) – FlyingTeller Jan 13 '22 at 15:35
  • 1
    `mochi = {}` does not create an empty dictionary for each call of the function, instead the same dictionary is used for each function call (with values added during previous calls still present) – FlyingTeller Jan 13 '22 at 15:36

1 Answers1

1

This is documented behavior when using mutables as default arguments (see "Default parameter values are evaluated from left to right when the function definition is executed.").

As discussed in the documentation, "A way around this is to use None as the default, and explicitly test for it in the body of the function".

[While documented, I only learned about it here on SO a couple of days ago]

jeguyer
  • 2,379
  • 1
  • 11
  • 15