'Returning None from python function

In a file called coke.py, implement a program that prompts the user to insert a coin, one at a time, each time informing the user of the amount due. Once the user has inputted at least 50 cents, output how many cents in change the user is owed. Assume that the user will only input integers, and ignore any integer that isn’t an accepted denomination.

Why does the amount_Due function return None not owed value when owed == 0

def main():

    owed = 50
    coin = check(owed)

    rem = amount_due(coin, owed)
    print(f"Change Owed: {rem}")

# check if the inserted coin is from coins or not

def check(owed):

    coins = [25, 10, 5]

    while True:
        print(f"Amout Due: {owed}")
        coin = int(input("Insert Coin: ").strip())
        if coin in coins:
            return coin

# calculate the remaning

def amount_due(coin, owed):
    owed -= coin
    if owed <= 0:
        return owed
    else:
        amount_due(check(owed), owed)

    


main()


Solution 1:[1]

It happens as an inner call comes back from the else block. You can see more detail about what is happening here with some extra prints in the area.

def amount_due(coin, owed):
    print(f"called with coin: {coin}; owed: {owed}")
    owed -= coin
    print(f"after decrement coin: {coin}; owed: {owed}")
    if owed == 0:
        pass
    else:
        amount_due(check(owed), owed)
    print(f"returning owed: {owed}")
    return owed

This allows this exchange:

Amout Due: 50
Insert Coin: 25
called with coin: 25; owed: 50
after decrement coin: 25; owed: 25
Amout Due: 25
Insert Coin: 25
called with coin: 25; owed: 25
after decrement coin: 25; owed: 0
returning owed: 0
returning owed: 25
Change Owed: 25

Wherein you can see that you are getting the 25 back from the inner call in the else block. You can kind of get around this with owed = amount_due(check(owed), owed), but there is probably a more simplified implementation that still follows a very similar pattern, without this particular nested call weirdness.

COINS = [5, 10, 25]


def main():
    owed = 50
    while owed > 0:
        owed = check(owed)


def get_input():
    coin = int(input("insert coin: ").strip())
    if coin not in COINS:
        print(f"must be one of: {COINS}")
        coin = get_input()
    return coin


def check(owed):
    if owed > 0:
        print(f"still owed: {owed}")
        owed -= get_input()
    return owed


main()

which yields the following exchange:

still owed: 50
insert coin: 25
still owed: 25
insert coin: 3
must be one of: [5, 10, 25]
insert coin: 25

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 theherk