Today: realism, main args, nested loop parsing

How Do Command Line Arguments Work?

Python-Main Guide

Command Line Examples

-affirm and -hello options

$ python3 affirm.py -affirm Lisa
Everything is coming up Lisa
$ python3 affirm.py -affirm Bart
Looking good Bart
$ python3 affirm.py -affirm Maggie
Today is the day for Maggie
$ python3 affirm.py -hello Bob
Hello Bob
$

Command Line Option e.g. -affirm

main()

Command Line Args - args list

$ python3 affirm.py -affirm Lisa
   ....
   e.g. args = ['-affirm', 'Lisa']


$ python3 affirm.py -affirm Bart
    ....
    e.g. args = ['-affirm', 'Bart']

Background: have print_affirm() etc. Functions to Call

Functions that do the work, main() will call them. In this case the functions are quite simple, but the key pattern is that main() can call functions, passing in the right data as their parameters.

def print_affirm(name):
    """
    Given name, print a random affirmation for that name.
    """
    affirmation = random.choice(AFFIRMATIONS)
    print(affirmation, name)


def print_hello(name):
    """
    Given name, print 'Hello' with that name.
    """
    print('Hello', name)


def print_n_copies(n, name):
    """
    Given int n and name, print n copies of that name.
    """
    for i in range(n):
        # Print each copy of the name with space instead of \n after it.
        print(name, end=' ')
    # Print a single \n after the whole thing.
    print()

How To Write main()

Code for -affirm

Make this command line work:

$ python3 affirm.py -affirm Lisa
def main():
    args = sys.argv[1:]
    ....
    ....
    # 1. Check for the -affirm arg pattern:
    #   python3 affirm.py -affirm Bart
    #   e.g. args[0] is '-affirm' and args[1] is 'Bart'

    if len(args) == 2 and args[0] == '-affirm':
        print_affirm(args[1])

Code for -hello

    if len(args) == 2 and args[0] == '-hello':
        print_hello(args[1])

Last Time: all_brackets

Link to all_brackets() etc. from previous lecture > loop/break/parse problems

We got to this at the end

def all_brackets(s):
    search = 0
    result = []
    while search < len(s):
        left = s.find('[', search)
        if left == -1:
            break

        # Your code here
        right = s.find(']', left + 1)
        if right == -1:
            break
        result.append(s[left + 1:right])
        # Key: set up var at end of loop
        search = right + 1
    return result

What about that < vs. if/break


Data and Parsing

Here's some fun looking data...

$GPGGA,005328.000,3726.1389,N,12210.2515,W,2,07,1.3,22.5,M,-25.7,M,2.0,0000*70
$GPGSA,M,3,09,23,07,16,30,03,27,,,,,,2.3,1.3,1.9*38
$GPRMC,005328.000,A,3726.1389,N,12210.2515,W,0.00,256.18,221217,,,D*78
$GPGGA,005329.000,3726.1389,N,12210.2515,W,2,07,1.3,22.5,M,-25.7,M,2.0,0000*71
$GPGSA,M,3,09,23,07,16,30,03,27,,,,,,2.3,1.3,1.9*38
$GPRMC,005329.000,A,3726.1389,N,12210.2515,W,0.00,256.18,221217,,,D*79
$GPGGA,005330.000,3726.1389,N,12210.2515,W,2,07,1.3,22.5,M,-25.7,M,3.0,0000*78
$GPGSA,M,3,09,23,07,16,30,03,27,,,,,,2.3,1.3,1.9*38
...

Parse-Words Example Functions

> parse-words example functions

1. at_words(s)

at_words(s): For each '@' in s, parse out the "word" substring of 1 or more alphabetic chars which immediately follow the '@', so '@abc @ @xyz' returns ['abc', 'xyz'].

Solution

def at_words(s):
    search = 0
    words = []
    while True:
        at = s.find('@', search)
        if at == -1:
            break
            
        # Pass over alpha chars to find end
        end = at + 1
        while end < len(s) and s[end].isalpha():
            end += 1
        
        word = s[at + 1:end]
        # Screen out len-0 word
        if len(word) > 0:
            words.append(word)
        
        # Set up next iteration
        search = end
    return words

at_word() #1 Done Test

at_word() #2 Find End of Alpha Chars

    while s[end].isalpha():
        end += 1

at_word() #3 Observations

2. exclaim_words(s) - You Try It

exclaim_words(s): For each '!' in s, parse out the "word" substring of one or more alphabetic chars which are immediately to the left of the '!'. Return a list of all such words including the '!', so 'x hey!@ho! returns ['hey!', 'ho!']. (Like at_words, but right-to-left)

3. parse_words(s)

parse_words(s): Given a string s, parse out and return all "words", where a word is made of 1 or more adjacent alphabetic chars, so '^ abc xyz$' returns ['abc', 'xyz'].

Solution

def parse_words(s):
    search = 0
    words = []
    while True:
        # Find a first alpha char (note: not)
        begin = search
        while begin < len(s) and not s[begin].isalpha():
            begin += 1
        
        # No alphas found -> done
        if begin >= len(s):
            break
        
        # Move end past the group of alphas
        end = begin + 1
        while end < len(s) and s[end].isalpha():
            end += 1
        
        # Now we know where it is
        word = s[begin:end]
        words.append(word)
        search = end + 1
    return words

More Practice Problems

A first goal is being able to solve 1-3, which are hard enough. Later we may look at the 4-7 problems.