Style
I suggest you check PEP0008 https://www.python.org/dev/peps/pep-0008/ the official Python style guide to give you some insights on how to write a Pythonic style code.
def change_return(cost,paid):
Docstrings: Python Docstring is the documentation string which is string literal, and it occurs in the class, module, function or method definition, and it is written as a first statement. Docstrings are accessible from the doc attribute for any of the Python object and also with the built-in help() function can come in handy. You should include a docstrings to your functions explaining what they do and what they return:
def calculate_total_change(cost, paid):
"""Calculate change and return total"""
# code
f-Strings PEP 498 introduced a new string formatting mechanism known as Literal String Interpolation or more commonly as F-strings (because of the leading f character preceding the string literal). ... In Python source code, an f-string is a literal string, prefixed with 'f', which contains expressions inside braces and this facilitates the insertion of variables in strings.
print(key + ': ' + str(value))
can be written:
print(f'{key}: {value}')
Blank lines: Too much blank lines in your function:
PEP008: Surround top-level function and class definitions with two blank lines.
Method definitions inside a class are surrounded by a single blank line.
Extra blank lines may be used (sparingly) to separate groups of related functions. Blank lines may be omitted between a bunch of related one-liners (e.g. a set of dummy implementations).
Use blank lines in functions, sparingly, to indicate logical sections.
Code
A function should return a function usually returns something instead of printing.
else:
print('Insufficient funds')
for key,value in change_dict.items():
if value > 0:
print(key + ': ' + str(value))
You might do the following instead:
return change_dict
Then use if __name__ == '__main__':
guard at the end of your script which allows other modules to import your module without running the whole script like this:
if __name__ == '__main__':
change = change_return(15, 20)
if change:
for unit, value in change.items():
print(f'{value}: {unit}')
if not change:
print('Amount paid is exact.')
Here's a refactored version of your code:
from fractions import Fraction
def calculate_total_change(cost, paid):
"""
cost: a float/int representing the total cost.
paid: a float/int representing amount paid
return: Total change (dictionary).
"""
units = [('Twenties', 20), ('Tens', 10), ('Fives', 5), ('Ones', 1), ('Quarters', Fraction(1 / 4)),
('Dimes', Fraction(1 / 10)), ('Nickels', Fraction(5 / 100)), ('Pennies', Fraction(1 / 100))]
total_change = {unit[0]: 0 for unit in units}
if cost > paid:
raise ValueError(f'Insufficient amount {paid} for cost {cost}.')
if cost == paid:
print('No change.')
return {}
if cost < paid:
change = paid - cost
if change:
for unit in units:
while change - unit[1] >= 0:
total_change[unit[0]] += 1
change -= unit[1]
return total_change
if __name__ == '__main__':
change = calculate_total_change(15, 22.5)
if change:
for unit, value in change.items():
print(f'{unit}: {value}')
else:
print('Amount exact')