0

I need a counter variable k that needs to be defined outside the function where it is updated (this is because I want define a recursive function). I found out that I can only do this if k is an element of a list:

def g(k):
    k +=1
    return 
​
def f():
    k = 0
    g(k)
    return k
​
f()
0

vs.

def g(k):
    k[0] +=1
    return

def f():
    k = [0]
    g(k)
    return k[0]
f()
1

Why is this? Is there a better way of doing this?

Below I show the real code:

def coins(n, m_25, m_10, m_5, m_1, m_tot, count):

    if m_tot == n:
        count[0] +=1
        return

    if m_tot > n:
        return

    coins(n, m_25+1, m_10, m_5, m_1, m_tot+25, count)
    coins(n, m_25, m_10+1, m_5, m_1, m_tot+10, count)
    coins(n, m_25, m_10, m_5+1, m_1, m_tot+5, count)
    coins(n, m_25, m_10, m_5, m_1+1, m_tot+1, count)

def get_coins(n, m_25, m_10, m_5, m_1, m_tot):
    count = [0]
    coins(n, m_25, m_10, m_5, m_1, m_tot, count)
    return count[0]
5
  • Is the final counter the only thing you're interested in returning? Commented Feb 27, 2020 at 0:15
  • @SyntaxVoidsupportsMonica yes. Commented Feb 27, 2020 at 0:16
  • " need a counter variable k that needs to be defined outside the function where it is updated (this is because I want define a recursive function)" You don't have to do it that way because it is recurisve... Commented Feb 27, 2020 at 0:28
  • @juanpa.arrivillaga how can initialize the value of the counter inside a recursive function? As far as I can see, its value would be set to 0 with each recursive call, which I don't want. Commented Feb 27, 2020 at 0:40
  • @Mencia you use an accumulator argument Commented Feb 27, 2020 at 0:41

2 Answers 2

1

Since the OP says they're only interested in returning the counter, we can set the recursive function to return the current counter and increment it by 1 every time it calls itself.

Edit: Changed the default count to 1 instead of 0 since (logically) the first time the function is called.. the counter should be set to 1.

A small sample would look like:

def func(x, count=1):
    if x >= 10: # Example base case
        return count
    return func(x+1, count+1)

print(f"Counter result = {func(-4)}")
# >> 15

Or, applied to the OP's actual code: (disclaimer: I don't really know what your code is supposed to do so you may need to slightly change the logic regarding when count is incremented. You also never use m_25, m_10, m_5, or m_1 in your code so I really have no idea what this function is supposed to do)

def coins(n, m_25, m_10, m_5, m_1, m_tot, count=1):
    if m_tot == n:
        count +=1
        return count
    if m_tot > n:
        return count
    count = coins(n, m_25+1, m_10, m_5, m_1, m_tot+25, count)
    count = coins(n, m_25, m_10+1, m_5, m_1, m_tot+10, count)
    count = coins(n, m_25, m_10, m_5+1, m_1, m_tot+5, count)
    count = coins(n, m_25, m_10, m_5, m_1+1, m_tot+1, count)
    return count

def get_coins(n, m_25, m_10, m_5, m_1, m_tot):
    return coins(n, m_25, m_10, m_5, m_1, m_tot)

print(f"Coins: {get_coins(10, 2, 3, 1, 5, 2)}") 
# >> 6
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the answer. I do use m_25 ... m_1 in the code as I change their value on the recursive calls. I am trying to count the number of ways to get n cents using coins of 25, 10, 5 and 1 cents. My code doesn't give the right answer because it considers 5+1 and 1+5 as two different combinations.
You do use them as arguments to your recursive call, but you don't do anything with them. You could delete all references of m_25, m_10, m_5, and m_1 and the result would still be the same. Is m_tot supposed to be the sum of all your coins? i.e. should m_tot equal m_25*25 + m_10*10 + …?
1

How about returning the value to the calling function like this?

def g(k):
    return k + 1

def f():
    k = 0
    return g(k)


print(f())

The reason your list works, is because lists are mutable data structure which is passed to g. Contrary to this, integers are immutable, so when you assign to the same name as an existing integer of the same scope, a new integer is created in memory and assigned to that name.

3 Comments

You are right when you say integers aren't mutable, however a copy is not passed to g. The int object being passed is the original integer (you can check this yourself by checking id(k) in each function). Instead, what's really happening when you say x += 1 is you are creating a new integer on the right hand side (equal to x+1) and then storing that as the value for x in the current namespace
Thanks for the explanation. Your solution, doesn't really work for me, see my edit above.
Mutable objects are not passed by reference in Python. Python uses a single evaluation strategy regardless of the type of object being passed, and it is neither call by reference nor call by value.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.