Python Virtual Training For Arcesium - Module II - Nurturing Session¶

Jul 7, 2022 Vikrant Patil

All notes are available online at https://notes.pipal.in/2022/arcesium_finop_batch1/

This page is available live at https://notes.pipal.in/2022/arcesium_finop_batch1/nurturing-session2.html

Please accept the invitation that you have received in your email and login to

https://engage.pipal.in/

© Pipal Academy LLP

Problems Briefing¶

Command tail¶

In [1]:
!head -n 5 zen.txt
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
In [3]:
!tail -n 5 zen.txt # it shows last 5 lines of file
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
  • Write a python script tail.py which mimics unix command tail. The command will show last few lines of a file. It takes filename as argument and optional argument -n to specify how many lines to display. By default it displays last 5 lines of the file.
$ python tail.py --help
Usage: tail.py [OPTIONS] FILENAME

Arguments:
  FILENAME  [required]

Options:
  -n INTEGER                      Number of lines to display  [default: 5]
  --install-completion [bash|zsh|fish|powershell|pwsh]
                                  Install completion for the specified shell.
  --show-completion [bash|zsh|fish|powershell|pwsh]
                                  Show completion for the specified shell, to
                                  copy it or customize the installation.
  --help                          Show this message and exit.


$ python tail.py zen.txt
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
In [4]:
!head --help
Usage: head [OPTION]... [FILE]...
Print the first 10 lines of each FILE to standard output.
With more than one FILE, precede each with a header giving the file name.

With no FILE, or when FILE is -, read standard input.

Mandatory arguments to long options are mandatory for short options too.
  -c, --bytes=[-]NUM       print the first NUM bytes of each file;
                             with the leading '-', print all but the last
                             NUM bytes of each file
  -n, --lines=[-]NUM       print the first NUM lines instead of the first 10;
                             with the leading '-', print all but the last
                             NUM lines of each file
  -q, --quiet, --silent    never print headers giving file names
  -v, --verbose            always print headers giving file names
  -z, --zero-terminated    line delimiter is NUL, not newline
      --help     display this help and exit
      --version  output version information and exit

NUM may have a multiplier suffix:
b 512, kB 1000, K 1024, MB 1000*1000, M 1024*1024,
GB 1000*1000*1000, G 1024*1024*1024, and so on for T, P, E, Z, Y.

GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Full documentation at: <https://www.gnu.org/software/coreutils/head>
or available locally via: info '(coreutils) head invocation'
In [5]:
%%file head.py
import typer


def head(filename, n):
    pass


if __name__ == "__main__":
    typer.run(head)
Overwriting head.py
In [6]:
!python head.py --help
Usage: head.py [OPTIONS] FILENAME N

Arguments:
  FILENAME  [required]
  N         [required]

Options:
  --install-completion [bash|zsh|fish|powershell|pwsh]
                                  Install completion for the specified shell.
  --show-completion [bash|zsh|fish|powershell|pwsh]
                                  Show completion for the specified shell, to
                                  copy it or customize the installation.
  --help                          Show this message and exit.
  • Argument - These are by position
  • Option - These are given with a flag
In [7]:
%%file head.py
import typer


def head(filename:str, n:int): # type annotations
    print("filename", type(filename))
    print("n", type(n))


if __name__ == "__main__":
    typer.run(head)
Overwriting head.py
In [8]:
!python head.py --help
Usage: head.py [OPTIONS] FILENAME N

Arguments:
  FILENAME  [required]
  N         [required]

Options:
  --install-completion [bash|zsh|fish|powershell|pwsh]
                                  Install completion for the specified shell.
  --show-completion [bash|zsh|fish|powershell|pwsh]
                                  Show completion for the specified shell, to
                                  copy it or customize the installation.
  --help                          Show this message and exit.
In [9]:
!python head.py zen.txt 3
filename <class 'str'>
n <class 'int'>
In [10]:
!python head.py 3 zen.txt # order is important
Usage: head.py [OPTIONS] FILENAME N
Try 'head.py --help' for help.

Error: Invalid value for 'N': 'zen.txt' is not a valid integer.
In [ ]:
%%file head.py
import typer


def head(filename:str, n:int=type.Option()): # type annotations
    print("filename", type(filename))
    print("n", type(n))


if __name__ == "__main__":
    typer.run(head)
In [11]:
int("sadasd")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Input In [11], in <cell line: 1>()
----> 1 int("sadasd")

ValueError: invalid literal for int() with base 10: 'sadasd'
In [12]:
int("zen.txt")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Input In [12], in <cell line: 1>()
----> 1 int("zen.txt")

ValueError: invalid literal for int() with base 10: 'zen.txt'
In [19]:
def myint(strdata):
    try:
        return int(strdata)
    except Exception as e: # catching of exception
        print(strdata, "can not be converted to int")
In [17]:
myint("34")
Out[17]:
34
In [18]:
myint("zen.txt")
zen.txt can not be converted to int
In [22]:
%%file head.py
import typer


def head(filename:str, n:int=typer.Option(5, "-n", help="Number of lines to be displayed")): # type annotations
    print("filename", type(filename))
    print("n", type(n))


if __name__ == "__main__":
    typer.run(head)
Overwriting head.py
In [23]:
!python head.py --help
Usage: head.py [OPTIONS] FILENAME

Arguments:
  FILENAME  [required]

Options:
  -n INTEGER                      Number of lines to be displayed  [default:
                                  5]
  --install-completion [bash|zsh|fish|powershell|pwsh]
                                  Install completion for the specified shell.
  --show-completion [bash|zsh|fish|powershell|pwsh]
                                  Show completion for the specified shell, to
                                  copy it or customize the installation.
  --help                          Show this message and exit.
In [24]:
!python head.py zen.txt
filename <class 'str'>
n <class 'int'>
In [25]:
!python head.py -n 3 zen.txt
filename <class 'str'>
n <class 'int'>
In [26]:
%%file head.py
import typer


def head(filename:str, n:int=typer.Option(5, "-n", help="Number of lines to be displayed")): # type annotations
    with open(filename) as f:
        for i in range(n):
            print(f.readline(), end="")
            
if __name__ == "__main__":
    typer.run(head)
Overwriting head.py
In [27]:
!python head.py -n 3 zen.txt
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
In [28]:
!python head.py -n 5 zen.txt
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
In [29]:
!python head.py zen.txt
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
In [30]:
with open("zen.txt") as f:
    f.readlines() # read all the lines as a list!
In [32]:
import typer
help(typer.Option)
Help on function Option in module typer.params:

Option(default: Optional[Any], *param_decls: str, callback: Optional[Callable[..., Any]] = None, metavar: Optional[str] = None, expose_value: bool = True, is_eager: bool = False, envvar: Union[str, List[str], NoneType] = None, shell_complete: Optional[Callable[[click.core.Context, click.core.Parameter, str], Union[List[ForwardRef('click.shell_completion.CompletionItem')], List[str]]]] = None, autocompletion: Optional[Callable[..., Any]] = None, show_default: bool = True, prompt: Union[bool, str] = False, confirmation_prompt: bool = False, prompt_required: bool = True, hide_input: bool = False, is_flag: Optional[bool] = None, flag_value: Optional[Any] = None, count: bool = False, allow_from_autoenv: bool = True, help: Optional[str] = None, hidden: bool = False, show_choices: bool = True, show_envvar: bool = True, case_sensitive: bool = True, min: Union[int, float, NoneType] = None, max: Union[int, float, NoneType] = None, clamp: bool = False, formats: Optional[List[str]] = None, mode: Optional[str] = None, encoding: Optional[str] = None, errors: Optional[str] = 'strict', lazy: Optional[bool] = None, atomic: bool = False, exists: bool = False, file_okay: bool = True, dir_okay: bool = True, writable: bool = False, readable: bool = True, resolve_path: bool = False, allow_dash: bool = False, path_type: Union[NoneType, Type[str], Type[bytes]] = None, rich_help_panel: Optional[str] = None) -> Any

Print Triangle¶

  • Write a script print_triangle.py to print a triangle of made of character * and of base n
python print_triangle.py 5
     *
    * *
   * * *
 * * * * *
* * * * * *
In [33]:
"hello".center(10) # 
Out[33]:
'  hello   '
In [ ]:
line.center(n+n-1)

Maximum Expenses¶

  • One year statement for a customer of an e-wallet is given in CSV format. Write a function maximum_expense that finds a row with maximum expense from the file. hint: make use of csv.DictReader. Here are first few lines of wallet statement.
date,category,description,debit
2021-03-07 14:53:28.377359,Music,Amazon,421.2073272347991
2020-10-08 09:53:28.377359,Food,Swiggy,328.4400802428426
2021-02-23 09:53:28.377359,Books,Amazon,244.67943701511356
2020-11-01 14:53:28.377359,Utility,Phone,222.7563175805277
2021-06-05 13:53:28.377359,Books,Flipcart,494.1284923793595
>>> maximum_expense('wallet.csv')
{'date': '2021-05-14 10:53:28.377359',
 'category': 'Utility',
 'description': 'Phone',
 'debit': '499.8581815222449'}
In [34]:
import csv
In [35]:
with open("wallet.csv") as f:
    creader = csv.DictReader(f)
    count = 0
    for row in creader:
        print(row)
        count = count + 1
        if count > 5:
            break
{'date': '2021-03-07 14:53:28.377359', 'category': 'Music', 'description': 'Amazon', 'debit': '421.2073272347991'}
{'date': '2020-10-08 09:53:28.377359', 'category': 'Food', 'description': 'Swiggy', 'debit': '328.4400802428426'}
{'date': '2021-02-23 09:53:28.377359', 'category': 'Books', 'description': 'Amazon', 'debit': '244.67943701511356'}
{'date': '2020-11-01 14:53:28.377359', 'category': 'Utility', 'description': 'Phone', 'debit': '222.7563175805277'}
{'date': '2021-06-05 13:53:28.377359', 'category': 'Books', 'description': 'Flipcart', 'debit': '494.1284923793595'}
{'date': '2021-07-28 19:53:28.377359', 'category': 'Utility', 'description': 'Electricity', 'debit': '219.94171130968408'}
In [38]:
records = [
    {'date': '2021-03-07 14:53:28.377359', 'category': 'Music', 'description': 'Amazon', 'debit': '421.2073272347991'},
{'date': '2020-10-08 09:53:28.377359', 'category': 'Food', 'description': 'Swiggy', 'debit': '328.4400802428426'},
{'date': '2021-02-23 09:53:28.377359', 'category': 'Books', 'description': 'Amazon', 'debit': '244.67943701511356'},
{'date': '2020-11-01 14:53:28.377359', 'category': 'Utility', 'description': 'Phone', 'debit': '222.7563175805277'},
{'date': '2021-06-05 13:53:28.377359', 'category': 'Books', 'description': 'Flipcart', 'debit': '494.1284923793595'},
{'date': '2021-07-28 19:53:28.377359', 'category': 'Utility', 'description': 'Electricity', 'debit': '219.94171130968408'}]
In [39]:
def get_debit(row):
    return float(row['debit'])
max(records, key=get_debit)
Out[39]:
{'date': '2021-06-05 13:53:28.377359',
 'category': 'Books',
 'description': 'Flipcart',
 'debit': '494.1284923793595'}

Total Expenses¶

  • Write a function total_expenses that reads data from csv file and computes total expenses for given category. One year statement for a customer of a online wallet is given in CSV format. There are five categories of expenses for that customer as 'Music', 'Food', 'Books', 'Utility' and 'Travel'. Write a function total_expenses that finds total expenses for given category. Here are first few lines of file
date,category,description,debit
2021-03-07 14:53:28.377359,Music,Amazon,421.2073272347991
2020-10-08 09:53:28.377359,Food,Swiggy,328.4400802428426
2021-02-23 09:53:28.377359,Books,Amazon,244.67943701511356
2020-11-01 14:53:28.377359,Utility,Phone,222.7563175805277
2021-06-05 13:53:28.377359,Books,Flipcart,494.1284923793595
>>> total_expenses('wallet.csv', 'Music')
4233.451868
In [40]:
def total_expenses(filename, category):
    # all the things required to read csv file
    
    for row in creader:
        if row['category'] == category:
            total += row['debit']
            
In [41]:
def total_expenses_forall(filename):
    # all the things required to read csv file
    with open(filename) as f:
        creader = csv.DictReader(f)
        total = {} 
        for row in creader:
            total[row['category']] = total.get(row['category'], 0) + float(row['debit'])
        
        return total
In [42]:
total_expenses_forall("wallet.csv")
Out[42]:
{'Music': 4233.451868232711,
 'Food': 8281.189172581231,
 'Books': 4929.750393283798,
 'Utility': 7562.267232638568,
 'Travel': 6052.931876440963}

Timer¶

  • Write a class Timer that can be used to find out time taken by some code execution. Make use of time.time function to get current time stamp in seconds.
timer = Timer()
timer.start()
time.sleep(2)
timer.stop(2)
print(time.time_elapsed())
2.000
In [43]:
import time
In [44]:
time.time() # this is current timestampt
Out[44]:
1659592392.1399195
In [45]:
time.time()
Out[45]:
1659592406.7476387
In [47]:
start = time.time()
time.sleep(2)
end = time.time()
In [48]:
end-start
Out[48]:
2.00156831741333
In [49]:
class BankAccount:
    
    def __init__():
        self.balance = 0
        
    def deposite(amount):
        self.balance += amount

center align¶

Write a program centeralign.py to center align all lines in the given file.

$ cat poem.txt
There was an Old Man with a beard
Who said, "It is just as I feared!
Two Owls and a Hen,
Four Larks and a Wren,
Have all built their nests in my beard!"

$ python centeralign.py poem.txt
   There was an Old Man with a beard
   Who said, "It is just as I feared!
          Two Owls and a Hen,
         Four Larks and a Wren,
Have all built their nests in my beard!"
In [ ]:
maxlinelength = find?
"hello".center(maxlinelength)
In [50]:
words = ["one", "two", "three", "four", "five"]
max(words, key=len)
Out[50]:
'three'

Questions¶

  • Modules
  • classes
  • functions
  • commands
In [53]:
def sumofsquares(a, b):
    def square(x):
        return x*x
    
    return square(a) + square(b)
In [54]:
sumofsquares(5, 4)
Out[54]:
41
In [56]:
sqaure(5) # 
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Input In [56], in <cell line: 1>()
----> 1 sqaure(5)

NameError: name 'sqaure' is not defined
In [57]:
!cat head.py
import typer


def head(filename:str, n:int=typer.Option(5, "-n", help="Number of lines to be displayed")): # type annotations
    with open(filename) as f:
        for i in range(n):
            print(f.readline(), end="")
            
if __name__ == "__main__":
    typer.run(head)
In [58]:
import head
In [66]:
head.head("wallet.csv", 5) # you have to pass all the required arguments!
date,category,description,debit
2021-03-07 14:53:28.377359,Music,Amazon,421.2073272347991
2020-10-08 09:53:28.377359,Food,Swiggy,328.4400802428426
2021-02-23 09:53:28.377359,Books,Amazon,244.67943701511356
2020-11-01 14:53:28.377359,Utility,Phone,222.7563175805277
In [60]:
class Foo:
    
    def method1(self, x, y):# althou self is first argument , while calling it you don't pass it!
        return x+y
In [61]:
f = Foo()
In [63]:
f.method1(4, 5) # no need of passing self..this is method
Out[63]:
9
In [64]:
def method2(a, x, y):
    return x+y
In [65]:
method2(3, 4)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [65], in <cell line: 1>()
----> 1 method2(3, 4)

TypeError: method2() missing 1 required positional argument: 'y'
In [ ]: