Module 2 - Day 4

command line arguments with typer

typer is third party library which makes command line arguments very easy

%%file hello.py
import typer


def hello(name):
    print(f"Hello {name}, how are you doing?")

typer.run(hello)
Overwriting hello.py
!python hello.py --help
Usage: hello.py [OPTIONS] NAME

Arguments:
  NAME  [required]

Options:
  --help  Show this message and exit.
!python hello.py Arcesium
Hello Arcesium, how are you doing?
%%file sqaure.py
import typer

def square(x:float): # this expects x as float
    return x**2


def print_square(x:float):
    print(square(x))

typer.run(print_square)
Overwriting sqaure.py
!python sqaure.py --help
Usage: sqaure.py [OPTIONS] X

Arguments:
  X  [required]

Options:
  --help  Show this message and exit.
!python sqaure.py 5
25.0
%%file square1.py
import sys

def square(x:float): # this expects x as float
    return x**2

def print_square(x:float):
    print(square(x))

a = float(sys.argv[1])
print_square(a)
Writing square1.py
!python square1.py 5
25.0
!python square1.py --help
Traceback (most recent call last):
  File "/home/jupyter-vikrant/arcesium-python-2024/square1.py", line 9, in <module>
    a = float(sys.argv[1])
ValueError: could not convert string to float: '--help'
%%file square2.py
import sys

def square(x:float): # this expects x as float
    return x**2

def print_square(x:float):
    print(square(x))

def check_args():
    if sys.argv[1] == '--help':
       print("Usage: python square2.py N")
    else:
        return float(sys.argv[1])

a = check_args()
if a is not None:
    print_square(a)
Overwriting square2.py
!python square2.py --help
Usage: python square2.py N
!python square2.py 7
49.0
%%file head.py
import typer

def head(filename, n:int):
    with open(filename) as f:
        for i in range(n):
            print(f.readline(), end="")

typer.run(head)
Overwriting head.py
!python head.py --help
Usage: head.py [OPTIONS] FILENAME N

Arguments:
  FILENAME  [required]
  N         [required]

Options:
  --help  Show this message and exit.
!python head.py zen.txt 6
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
%%file head1.py
import typer

def head(filename, n:int=10):
    with open(filename) as f:
        for i in range(n):
            print(f.readline(), end="")

typer.run(head)
Overwriting head1.py
!python head1.py --help
Usage: head1.py [OPTIONS] FILENAME

Arguments:
  FILENAME  [required]

Options:
  --n INTEGER  [default: 10]
  --help       Show this message and exit.
!python head1.py --n 4 
Usage: head1.py [OPTIONS] FILENAME
Try 'head1.py --help' for help.

Error: Missing argument 'FILENAME'.
!python head1.py --n 4 zen.txt
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
cmd --arg1 v1 --arg3 v3 --arg4 v4 --arg5 v5 --arg2 v2
%%file head2.py
import typer

def head(filename, lines:int=10):
    with open(filename) as f:
        for i in range(lines):
            print(f.readline(), end="")

typer.run(head)
Overwriting head2.py
!python head2.py --help
Usage: head2.py [OPTIONS] FILENAME

Arguments:
  FILENAME  [required]

Options:
  --lines INTEGER  [default: 10]
  --help           Show this message and exit.
!python head2.py --lines 3 zen.txt
The Zen of Python, by Tim Peters

Beautiful is better than ugly.

problem

Write a function triangle to print a text triangle using any char that is passed

def triangle(base, char="*"):
    t = [char*i for i in range(1, base+1)]
    return t
triangle(5)
['*', '**', '***', '****', '*****']
    *
   * *
  * * *
 * * * *
* * * * *
"hello".center(50)
'                      hello                       '
def prety_print(t):
    width = len(t[-1])
    for row in t:
        print(row.center(width))
prety_print(triangle(3))
 * 
 **
***
def format_row(row):
    return " ".join(list(row))
    
def prety_print(t):
    width = len(t[-1])
    for row in t:
        row_ = format_row(row)
        print(row_.center(width))
prety_print(triangle(5))
  *  
 * * 
* * *
* * * *
* * * * *
def format_row(row):
    return " ".join(list(row))
    
def prety_print(t):
    basesize = len(t[-1])
    width  = basesize + basesize -1
    for row in t:
        row_ = format_row(row)
        print(row_.center(width))
prety_print(triangle(5))
    *    
   * *   
  * * *  
 * * * * 
* * * * *
prety_print(triangle(20, "@"))
                   @                   
                  @ @                  
                 @ @ @                 
                @ @ @ @                
               @ @ @ @ @               
              @ @ @ @ @ @              
             @ @ @ @ @ @ @             
            @ @ @ @ @ @ @ @            
           @ @ @ @ @ @ @ @ @           
          @ @ @ @ @ @ @ @ @ @          
         @ @ @ @ @ @ @ @ @ @ @         
        @ @ @ @ @ @ @ @ @ @ @ @        
       @ @ @ @ @ @ @ @ @ @ @ @ @       
      @ @ @ @ @ @ @ @ @ @ @ @ @ @      
     @ @ @ @ @ @ @ @ @ @ @ @ @ @ @     
    @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @    
   @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @   
  @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @  
 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ 
@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @
def triangle(base, char):
    for i in range(1, base+1):
        print(" "*(base-i) + f"{char} "*i)
triangle(5, "*")
    * 
   * * 
  * * * 
 * * * * 
* * * * * 
def triangle3(char, height):
    width = height * 2 - 1
    for i in range(1, height + 1):
        line = char * (2 * i - 1)
        print(line.center(width))
triangle3("*", 5) # base is not 5
    *    
   ***   
  *****  
 ******* 
*********
triangle3("*", 2)
 * 
***
t = """*
**
***
****
****"""
print(t)
*
**
***
****
****
t.center(50)
'                *\n**\n***\n****\n****                '
for line in t.split("\n"):
    print(line.center())
  *   
  **  
 ***  
 **** 
 **** 
*
* *      size 3
* * *    size 5
* * * *  size 7

Working with dictionaries

person = {"name" : "Vikrant",
          "email": "vikrant@pipalacademy",
          "address" : "Dapoli",
          "mobile" : 1111111111}
person
{'name': 'Vikrant',
 'email': 'vikrant@pipalacademy',
 'address': 'Dapoli',
 'mobile': 1111111111}
person['name']
'Vikrant'
person['mobile']
1111111111
person['address']
'Dapoli'
person['company']
KeyError: 'company'
person.get("company", "Arcesium")
'Arcesium'
person.get("name") # you can also get values using get method
'Vikrant'
person['name']
'Vikrant'
person.get("company", "Arcesium") # if the key is not present in the dictionary then don't throw error return the default value 
'Arcesium'
person
{'name': 'Vikrant',
 'email': 'vikrant@pipalacademy',
 'address': 'Dapoli',
 'mobile': 1111111111}
person['company'] = 'Pipal Academy'
person
{'name': 'Vikrant',
 'email': 'vikrant@pipalacademy',
 'address': 'Dapoli',
 'mobile': 1111111111,
 'company': 'Pipal Academy'}
person.get("company", "Arcesium") # return arcesium only if key and value pair for company is missing in the dictionary!
'Pipal Academy'
person.get("nationality") # if the "nationality" key is absent in the dictionary then return None
def foo():
    pass
foo()
def sqr(x):
    return x**2
sqr(5)
25
nat = person.get("nationality")
print(nat)
None
person['nationality']
KeyError: 'nationality'
for key in person:
    print(key)
name
email
address
mobile
company
for key in person:
    print(key, person[key])
name Vikrant
email vikrant@pipalacademy
address Dapoli
mobile 1111111111
company Pipal Academy
for value in person.values():
    print(value)
Vikrant
vikrant@pipalacademy
Dapoli
1111111111
Pipal Academy
for key, value in person.items():
    print(key, value)
name Vikrant
email vikrant@pipalacademy
address Dapoli
mobile 1111111111
company Pipal Academy
for key in person.keys():
    print(key)
name
email
address
mobile
company
for key in person:
    print(key)
name
email
address
mobile
company

Example : Find frequencies of words in given text file

%%file words.txt
one
one two 
one two three
one two three four
one two three four five
one two three four six
one two three six seven
one two six seven eight
one six seven eight nine
six seven eight nine ten
seven eight nine ten
eight nine ten
nine ten
ten
Writing words.txt
  • there is a file, read the file and get all the words: make a functions get_words
  • find frequencies given the words : word_frequency
    • Either you can loop over words and count
    • you can make use list method , count
filename = "words.txt"
get_words(filename)
get_words("words.txt")
def get_words(filepath):
    with open(filepath) as f:
        contents = f.read()
        words = contents.split()
        return words
get_words("words.txt")
['one',
 'one',
 'two',
 'one',
 'two',
 'three',
 'one',
 'two',
 'three',
 'four',
 'one',
 'two',
 'three',
 'four',
 'five',
 'one',
 'two',
 'three',
 'four',
 'six',
 'one',
 'two',
 'three',
 'six',
 'seven',
 'one',
 'two',
 'six',
 'seven',
 'eight',
 'one',
 'six',
 'seven',
 'eight',
 'nine',
 'six',
 'seven',
 'eight',
 'nine',
 'ten',
 'seven',
 'eight',
 'nine',
 'ten',
 'eight',
 'nine',
 'ten',
 'nine',
 'ten',
 'ten']
def get_words(filepath):
    with open(filepath) as f:
        contents = f.read()
        words = contents.split()
        return words
words = get_words("words.txt")
words.count("one")
9
def word_frequency(words):
    uniquewords = set(words) # set will convert the list into unique items
    freq = {}
    for word in uniquewords:
        f = words.count(word)
        freq[word] = f # here word is key and f is value

    return freq
word_frequency(words)
{'eight': 5,
 'ten': 5,
 'five': 1,
 'three': 5,
 'two': 7,
 'seven': 5,
 'six': 5,
 'one': 9,
 'nine': 5,
 'four': 3}
"hello hello ".count("hello")
2
d = {}
d['a'] = 1
l = []
l.append(1)
l.append(2)
d = dict()
d['a'] = 1
d['b']  = 2
d
{'a': 1, 'b': 2}
def squares(items):
    sqrs = []
    for n in items:
        sqrs.append(n**2)

    return sqrs
def squares(items):
    return [n**2 for n in items]
def word_frequency(words):
    uniquewords = set(words) # set will convert the list into unique items
    freq = {}
    for word in uniquewords:
        f = words.count(word)
        freq[word] = f # here word is key and f is value

    return freq

# dictionary comprehension
def word_frequency(words):
    uniquewords = set(words) # set will convert the list into unique items
    return {word: words.count(word) for word in uniquewords}
    
def word_frequency(words):
    uwords=[]
    freq={}
    for word in words:
        if word in uwords:
            pass
        else:
            uwords.append(word)
            freq[word] = words.count(word)

    return freq

def word_frequency(words):
    freq={}
    for word in words:    
        freq[word] = freq.get(word, 0) + 1 
            
    return freq

def word_frequency(words):# XXX : not possible
    return {freq.get(word, 0) + 1 for word in words}
word_frequency(words)
NameError: name 'freq' is not defined

def word_frequency(words):
    freq={}
    for word in words:    
        freq[word] = freq.get(word, 0) + 1 
            
    return freq
word_frequency(words)
{'one': 9,
 'two': 7,
 'three': 5,
 'four': 3,
 'five': 1,
 'six': 5,
 'seven': 5,
 'eight': 5,
 'nine': 5,
 'ten': 5}
freq = word_frequency(words)
for word, count in freq.items():
    print(word, count)
one 9
two 7
three 5
four 3
five 1
six 5
seven 5
eight 5
nine 5
ten 5
def get_freq(pair):
    return pair[1]

for word, count in sorted(freq.items(), key=get_freq):
    print(word, count)
five 1
four 3
three 5
six 5
seven 5
eight 5
nine 5
ten 5
two 7
one 9
def get_freq(pair):
    return pair[1]

for word, count in sorted(freq.items(), key=get_freq, reverse=True):
    print(word, count)
one 9
two 7
three 5
six 5
seven 5
eight 5
nine 5
ten 5
four 3
five 1
def get_freq(pair):
    return pair[1]

for word, count in sorted(freq.items(), key=get_freq, reverse=True):
    print(word.rjust(5), count)
  one 9
  two 7
three 5
  six 5
seven 5
eight 5
 nine 5
  ten 5
 four 3
 five 1
def get_freq(pair):
    return pair[1]

for word, count in sorted(freq.items(), key=get_freq, reverse=True):
    print(word.rjust(5), count, "*"*count)
  one 9 *********
  two 7 *******
three 5 *****
  six 5 *****
seven 5 *****
eight 5 *****
 nine 5 *****
  ten 5 *****
 four 3 ***
 five 1 *
max(freq.items(), key=get_freq)
('one', 9)
freq.items()
dict_items([('one', 9), ('two', 7), ('three', 5), ('four', 3), ('five', 1), ('six', 5), ('seven', 5), ('eight', 5), ('nine', 5), ('ten', 5)])
# dictionary comprehension
def word_frequency(words):
    uniquewords = set(words) # set will convert the list into unique items
    return {word: words.count(word) for word in uniquewords}
    
d = {"a":1, "b":2}
{key: compute_value(key) for key in collection}
{word: words.count(word) for word in uniquewords}
words
['one',
 'one',
 'two',
 'one',
 'two',
 'three',
 'one',
 'two',
 'three',
 'four',
 'one',
 'two',
 'three',
 'four',
 'five',
 'one',
 'two',
 'three',
 'four',
 'six',
 'one',
 'two',
 'three',
 'six',
 'seven',
 'one',
 'two',
 'six',
 'seven',
 'eight',
 'one',
 'six',
 'seven',
 'eight',
 'nine',
 'six',
 'seven',
 'eight',
 'nine',
 'ten',
 'seven',
 'eight',
 'nine',
 'ten',
 'eight',
 'nine',
 'ten',
 'nine',
 'ten',
 'ten']
wordlens = {word:len(word) for word in words}
wordlens
{'one': 3,
 'two': 3,
 'three': 5,
 'four': 4,
 'five': 4,
 'six': 3,
 'seven': 5,
 'eight': 5,
 'nine': 4,
 'ten': 3}
with open("words.txt") as f:
    text = f.read()
for key in wordlens:
    print(key, text.count(key))
one 9
two 7
three 5
four 3
five 1
six 5
seven 5
eight 5
nine 5
ten 5
for value in wordlens.values():
    print(value)
3
3
5
4
4
3
5
5
4
3

problem There is indexdata given as a list. Find weekly average for each stock.

  indexdata = [('IBM', 'Monday', 111.71436961893693),
          ('IBM', 'Tuesday', 141.21220022208635),
          ('IBM', 'Wednesday', 112.40571010053796),
          ('IBM', 'Thursday', 137.54133351926248),
          ('IBM', 'Friday', 140.25154281801224),
          ('MICROSOFT', 'Monday', 235.0403622499107),
          ('MICROSOFT', 'Tuesday', 225.0206535036475),
          ('MICROSOFT', 'Wednesday', 216.10342426936444),
          ('MICROSOFT', 'Thursday', 200.38038844494193),
          ('MICROSOFT', 'Friday', 235.80850482793264),
          ('APPLE', 'Monday', 321.49182055844256),
          ('APPLE', 'Tuesday', 340.63612771662815),
          ('APPLE', 'Wednesday', 303.9065277507285),
          ('APPLE', 'Thursday', 338.1350605764038),
          ('APPLE', 'Friday', 318.3912296144338)]

This is how we can store week averages weekly_average = {"IBM": ibmavaegra, "MICROSOFT": somevalue, "APPLE": another_value}

def get_prices(data, symbol):
    # will be list comprehension
    pass

def compute_mean(nums):
    return sum(nums)/len(nums)


def weekly_average(indexdata):
    avg = {}
    for symbol, day, price in indexdata:
        avg[symbol] = compute_mean(get_prices(indexdata, symbol))

    return avg

Homework

  • Complete above functionality
  • convert weekly_average function’s dictionary creation into dictionary comprehension