Python 3

home

Introduction to Python

davidbpython.com




Introduction to User-Defined Functions

Proper Code Organization

Core principles


Here are the main components of a properly formatted program:


""" tip_calculator.py -- calculate tip for a restaurant bill
    Author:  David Blaikie dbb212@nyu.edu
    Last modified:  9/19/2017
"""

import sys             # part of Python distribution (installed with Python)
import pandas as pd    # installed "3rd party" modules
import myownmod as mm  # "local" module (part of local codebase)


# constant message strings are not required to be placed
# here, but in professional programs they are kept
# separate from the logic, often in separate "config" files
MSG1 = 'A {}% tip (${}) was added to the bill, for a total of ${}.'
MSG2 = 'With {} in your party, each person must pay ${}.'


# sys.argv[0] is the program's pathname (e.g. /this/that/other.py)
# os.path.basename() returns just the program name (e.g. other.py)
USAGE_STRING = "Usage:  {os.path.basename(sys.argv[0])}   [total amount] [# in party] [tip percentage]


def usage(msg):
    """ print an error message, usage: string and exit

    Args:     msg (str):  an error message
    Returns:  None (exits from here)
    Raises:   N/A (does not explicitly raise an exception)

    """
    sys.stderr.write(f'Error:  {msg}')
    exit(USAGE_STRING)


def validate_normalize_input(args):
    """ verify command-line input

    Args:     N/A (reads from sys.argv)

    Returns:
        bill_amt (float):  the bill amount
        party_size (int):  the number of people
        tip_pct (float):   the percent tip to be applied, in 100’s

    Raises:  N/A (does not explicitly raise an exception)

    """
    if not len(sys.argv) == 4:
        usage('please enter all required arguments')

    try:
        bill_amt = float(sys.argv[1])
        party_size = int(sys.argv[2])
        tip_pct = float(sys.argv[3])
    except ValueError:
        usage('arguments must be numbers')

    return bill_amt, party_size, tip_pct


def perform_calculations(bill_amt, party_size, tip_pct):
    """
    calculate tip amount, total bill and person's share

    Args:
        bill_amount (float):  the total bill
        party_size (int):  the number in party
        tip_pct (float):  the tip percentage in 100’s

    Returns:
        tip_amt (float):  the tip in $
        total_bill (float):  the bill including tip
        person_share (float):  equal share of bill per person

    Raises:
        N/A (does not specifically raise an exception)
    """

    tip_amt = bill_amt * tip_pct * .01
    total_bill = bill_amt + tip_amt
    person_share = total_bill / party_size

    return tip_amt, total_bill, person_share


def report_results(pct, tip_amt, total_bill, size, person_share):
    """ print results in formatted strings

    Args:
        pct (float):  the tip percentage in 100’s
        tip_amt (float):  the tip in $
        total_bill (float):  the bill including tip
        size (int):  the party slize
        person_share (float):  equal share of bill per person
    Returns:
        None (prints result)

    Raises:
        N/A
    """

    print(MSG1.format(pct, tip_amt, total_bill))
    print(MSG2.format(size, person_share))


def main(args):
    """ execute script

    Args:     args (list):  the command-line arguments
    Returns:  None
    Raises:   N/A

    """

    bill, size, pct = validate_normalize_input(args)
    tip_amt, total_bill, person_share = perform_calculations(bill, size,
                                                             pct)

    report_results(pct, tip_amt, total_bill, size, person_share)


if __name__ == '__main__':            # 'main body' code

    main(sys.argv[1:])

The code inside the if __name__ == '__main__' block is intended to be the call that starts the program. If this Python script is imported, the main() function will not be called, because the if test will only be true if the script is executed, and will not be true if it is imported. We do this in order to allow the script's functions to be imported and used without actually running the script -- we may want to test the script's functions (unit testing) or make use of a function from the script in another program. Whether we intend to import a script or not, it is considered a "best practice" to build all of our programs in this way -- with a "main body" of statements collected under function main(), and the call to main() inside the if __name__ == '__main__' gate. This structure will be required for all assignments submitted for the remainder of the course.





user-defined functions

User-defined functions are a block of code that can be executed by name.


def add(val1, val2):
    valsum = val1 + val2
    return valsum

ret = add(5, 10)           # int, 15

ret2 = add(0.3, 0.9)       # float, 1.2

A function is a block of code:





user defined functions: calling the function

A user-defined function is simply a named code block that can be executed any number of times.


def print_hello():
    print("Hello, World!")

print_hello()             # prints 'Hello, World!'
print_hello()             # prints 'Hello, World!'
print_hello()             # prints 'Hello, World!'





user defined functions: arguments

The argument is the input to a function.


def print_hello(greeting, person):              # note we do not
    full_greeting = f'{greeting}, {person}!'    # refer to 'name1'
    print(full_greeting)                        # 'place2', etc.
                                                # inside the function
name1 = 'Hello'
place1 = 'World'

print_hello(name1, place1)             # prints 'Hello, World!'


name2 = 'Bonjour'
place2 = 'Python'

print_hello(name2, place2)             # prints 'Bonjour, Python!'





user defined functions: function return values

A function's return value is passed back from the function using the return statement.


def print_hello(greeting, person):
  full_greeting = f'{greeting}, {person}!'
  return full_greeting

msg = print_hello('Bonjour', 'parrot')

print(msg)                                       # 'Bonjour, parrot!'





[pr]