Python 3home |
Introduction to Python
davidbpython.com
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 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:
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!'
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!'
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!'