Programming basics for Biostatistics 6099

Basics of Python programming (part 2)

Zhiguang Huo (Caleb)

Thursday Oct 12th, 2023

Outlines

Control flows

num = input("Enter a number: ")
if int(num) > 0:
    print(f"{num} is positive")

Indentation

if else elif

num = input("Enter a number: ")
if int(num) > 0:
    print(f"{num} is positive")
else:
    print(f"{num} is not positive")
num = input("Enter a number: ")
if int(num) > 0:
    print("The number is positive")
elif int(num) < 0:
    print("The number is negative")
else:
    print("The number is zero")

if else same line

number = input("Please enter a number: ")
if int(number) % 2 == 0:
    print("even")
else:
    print("odd")
number = input("Please enter a number: ")
print("even") if int(number) % 2 == 0 else print("odd")

True or False conditions

1>2
## False
4 == 5
## False
"ap" in "apple"
## True
"apple" in ["apple", "orange"]
## True
True and False
## False
True or False
## True
not True
## False

True or False conditions

a = 4
b = 6
c = 9

a < b and b < c
## True
a < b < c
## True
a < c > b
## True

match (available for python >= 3.10)

status = 400    

match status:
    case 400:
        print("Bad request")
    case 404:
        print("Not found")
    case 418:
        print("I'm a teapot")
    case _:
        print("Something's wrong with the internet")
## Bad request

for loops

words = ["cat", "dog", "gator"]
for w in words:
     print(w)
## cat
## dog
## gator
words = ["cat", "dog", "gator"]
for w in words:
     print(f"{w} has {len(w)} letters in it.")
## cat has 3 letters in it.
## dog has 3 letters in it.
## gator has 5 letters in it.

range() function

for i in range(3):
    print(i)
## 0
## 1
## 2
list(range(3))
## [0, 1, 2]
list(range(3,7))
## [3, 4, 5, 6]

range() function

list(range(3,8,2))
## [3, 5, 7]
list(range(7,2,-2))
## [7, 5, 3]
words = ["cat", "dog", "gator"]
for i in range(len(words)):
     print(i, words[i])
## 0 cat
## 1 dog
## 2 gator

break

for num in range(1, 10):
  if num % 5 == 0:
    print(f"{num} can be divided by 5")
    break
  print(f"{num} cannot be divided by 5")
## 1 cannot be divided by 5
## 2 cannot be divided by 5
## 3 cannot be divided by 5
## 4 cannot be divided by 5
## 5 can be divided by 5

continue

for num in range(1, 10):
  if num % 5 == 0:
    continue
  print(f"{num} cannot be divided by 5")
## 1 cannot be divided by 5
## 2 cannot be divided by 5
## 3 cannot be divided by 5
## 4 cannot be divided by 5
## 6 cannot be divided by 5
## 7 cannot be divided by 5
## 8 cannot be divided by 5
## 9 cannot be divided by 5

pass

sequence = {'p', 'a', 's', 's'}
for val in sequence:
    pass
a = 33
b = 200

if b > a:
  pass

while loop

num = 1
while num<10:
  if num % 5 == 0:
    print(f"{num} can be divided by 5")
    break
  print(f"{num} cannot be divided by 5")
  num+=1
## 1 cannot be divided by 5
## 2 cannot be divided by 5
## 3 cannot be divided by 5
## 4 cannot be divided by 5
## 5 can be divided by 5
num = 0
while num<10:
  num+=1
  if num % 5 == 0:
    continue
  print(f"{num} cannot be divided by 5")
## 1 cannot be divided by 5
## 2 cannot be divided by 5
## 3 cannot be divided by 5
## 4 cannot be divided by 5
## 6 cannot be divided by 5
## 7 cannot be divided by 5
## 8 cannot be divided by 5
## 9 cannot be divided by 5

Basic string operators

find

title = "I love programming basics for Biostatistics!"
title.find("I")
## 0
title.find("love")
## 2
title.find("o")
## 3
title.find("o", 4) ## starting searching index is 4
## 9
title.find("XX")
## -1
title.index("love")
title.index("XX")

pattern detection

title = "I love programming basics for Biostatistics!"
"love" in title
## True
"computing" in title
## False
"XX" in title
## False
title.endswith("computing!")
## False
title.startswith("I love")
## True
title.count("l")
## 1

join

seq = ["1", "2", "3", "4", "5"]
sep = "+"
sep.join(seq)
## '1+2+3+4+5'
"".join(seq)
## '12345'
dirs =( "", "usr", "bin", "env")
"/".join(dirs)
## '/usr/bin/env'
sep = "+"
print("C:" + "\\".join(dirs)) ## single \ has special meaning: treating special symbol as regular symbol 
## C:\usr\bin\env

split

longSeq = "1+2+3+4+5"
longSeq.split("+")
## ['1', '2', '3', '4', '5']
longSeq.split("3")
## ['1+2+', '+4+5']
"Using the default value".split()
## ['Using', 'the', 'default', 'value']

lower, upper, title

sentence = "I like programming basics for Biostatistics!"
sentence.lower()
## 'i like programming basics for biostatistics!'
sentence.upper()
## 'I LIKE PROGRAMMING BASICS FOR BIOSTATISTICS!'
sentence.title()
## 'I Like Programming Basics For Biostatistics!'
sentence.islower()
sentence.isupper()
sentence.istitle()

strip

a = "   internal   whitespace is kept     "
a.strip()
## 'internal   whitespace is kept'
b = "*** SPAM * for * everyone!!! ***"
b.strip(" *!")
## 'SPAM * for * everyone'
c = "\na\nb\n\n\nc\n\n"
c.strip()
## 'a\nb\n\n\nc'

replace

a = "This is a cat!"
a.replace("This", "That")
## 'That is a cat!'
a.replace("is", "eez")
## 'Theez eez a cat!'

file operation (read)

https://caleb-huo.github.io/teaching/data/misc/my_file.txt

file = open("my_file.txt")
contents = file.read()
print(contents)
## Hello, my name is Caleb. Hello World!
## I like computing
file.close()
with open("my_file.txt") as file:
    contents = file.read()
    print(contents)
## Hello, my name is Caleb. Hello World!
## I like computing

file operation (read)

myfile = "my_file.txt"
with open(myfile) as file:
    lines = file.readlines()

for aline in lines:
    print(aline.strip())
## Hello, my name is Caleb. Hello World!
## I like computing

file operation (write)

with open("new_file.txt", mode="w") as file:
    file.write("I like python!")
## 14
with open("new_file.txt", mode="a") as file:
    file.write("We like python!")
## 15

Exceptions

with open("a_file.txt") as file:
    file.read()
fruit_list = ["Apple", "Banana", "Pear"]
fruit_list[3]
text = "abc"
print(text + 5)
raise TypeError("This is an error that I made up!")

Handle exceptions

try:
    file = open("a_file.txt")
    print(1 + "2")
except FileNotFoundError:
    print("Catch FileNotFoundError")
except TypeError as error_message:
    print(f"Here is the error: {error_message}.")
else:
    content = file.read()
    print(content)
finally: ## will happen no matter what happens
    file.close()
    print("File was closed.")
## Catch FileNotFoundError
## File was closed.

datetime

import datetime as dt
now = dt.date.today() ## date only
now.year
## 2023
now.month
## 10
now.day
## 12
# now.weekday()
birthday = dt.date(1995, 7, 31)
age = now - birthday
age.days
## 10300

datetime

now = dt.datetime.now()
now.year
## 2023
now.month
## 10
now.day
## 12
now.hour
## 13
now.minute
## 18
now.second
## 59
now.microsecond
## 756676
now.weekday()
## 3

datetime

now = dt.datetime.now()

print(f'{now:%Y-%m-%d %H:%M}')
## 2023-10-12 13:18

more on python data structure

list: creation and assignment

list("Hello")
## ['H', 'e', 'l', 'l', 'o']
x = [1, 1, 1]
x
## [1, 1, 1]
x = [1, 2, 3]
x[1] = 0
x
## [1, 0, 3]

list: deletion and slice assignment

names = ["Alice", "Beth", "Carl", "Dan", "Emily"]
names
## ['Alice', 'Beth', 'Carl', 'Dan', 'Emily']
del names[2]
names
## ['Alice', 'Beth', 'Dan', 'Emily']
names = list("Lucas")
names[3:] = list("ky")
names
## ['L', 'u', 'c', 'k', 'y']
"".join(names)
## 'Lucky'
names = list("Lucas")
names[1:] = list("emonade")
"".join(names)
## 'Lemonade'
numbers = [1, 5]
numbers[1:1] = [2, 3, 4]
numbers
## [1, 2, 3, 4, 5]
numbers = list(range(1,6))
numbers
## [1, 2, 3, 4, 5]
numbers[1:4] = []
numbers
## [1, 5]

list: append and count

alist = [0,1,2]
alist.append(3)
alist
## [0, 1, 2, 3]
asentence = "to be or not to be"
alist = asentence.split()
alist.count("to")
## 2
x = [[1,2], 1, 2, 1, [2, 1, [1,2]]]
x.count(1)
## 2
x.count([1,2])
## 1

list: extend

a = [0,1,2]; b = [3,4,5]
a.extend(b)
a
## [0, 1, 2, 3, 4, 5]
a = [0,1,2]; b = [3,4,5]
a + b
## [0, 1, 2, 3, 4, 5]
a
## [0, 1, 2]
a = [0,1,2]; b = [3,4,5]
a[len(a):] = b
a
## [0, 1, 2, 3, 4, 5]

list: index

asentence = "to be or not to be"
alist = asentence.split()
alist
## ['to', 'be', 'or', 'not', 'to', 'be']
alist.index("to")
## 0
alist.index("not")
## 3
alist[3]
## 'not'
alist.index("XX")

list: insert

alist = [1,2,3,5,6]
alist.insert(3, "four")
alist
## [1, 2, 3, 'four', 5, 6]
alist = [1,2,3,5,6]
alist[3:3] = ["four"]
alist
## [1, 2, 3, 'four', 5, 6]

list: pop

x = list(range(10))
x.pop()
## 9
x
## [0, 1, 2, 3, 4, 5, 6, 7, 8]
x.pop()
## 8
x
## [0, 1, 2, 3, 4, 5, 6, 7]

list: remove

asentence = "to be or not to be"
alist = asentence.split()
alist
## ['to', 'be', 'or', 'not', 'to', 'be']
alist.remove("to")
alist
## ['be', 'or', 'not', 'to', 'be']
alist.remove("XX")

list: reverse and sort

x = ["a", "b", "c"]
x.reverse()
x
## ['c', 'b', 'a']
x = [5, 3, 4]
x.sort() 
x
## [3, 4, 5]
y = ["b", "c", "a"]
y.sort()
y
## ['a', 'b', 'c']
x = [5, 3, 4]
y = x.sort() 
print(y)
## None
x = [5, 3, 4]
y = sorted(x) 
print(y)
## [3, 4, 5]

list: sort

x = [5, 3, 4]
y = x ## x and y are pointing to the same list
y.sort() 

print(x)
## [3, 4, 5]
print(y)
## [3, 4, 5]
x = [5, 3, 4]
y = x[:] ## y is a slice assignment of x, thus a new variable
y.sort() 

print(x)
## [5, 3, 4]
print(y)
## [3, 4, 5]

references and values

list: sort

x = ["aaa", "bb", "cccc"]
x.sort(key = len) 
x
## ['bb', 'aaa', 'cccc']
x = [5, 3, 4]
x.sort(reverse = True) 
print(x)
## [5, 4, 3]

dictionary: basic operator

phonebook = {"Alice": 2341, 
            "Beth": 4971,
            "Carl": 9401
}
phonebook
## {'Alice': 2341, 'Beth': 4971, 'Carl': 9401}
len(phonebook)
## 3
phonebook["Beth"]
## 4971

dictionary: update and delete

phonebook["Alice"] = 1358
phonebook
## {'Alice': 1358, 'Beth': 4971, 'Carl': 9401}
adict = {"Alice": 9572}
phonebook.update(adict)
phonebook
## {'Alice': 9572, 'Beth': 4971, 'Carl': 9401}
del phonebook["Carl"]
"Beth" in phonebook
## True

dictionary: clear

d = {}
d['name'] = "Amy"
d['age'] = 24
d
## {'name': 'Amy', 'age': 24}
d.clear()
d
## {}

why clear is useful

x = {}
y = x
x['key'] = 'value'
y
## {'key': 'value'}
x = {} ## now x points to a new value {}
y ## y points to the original value {'key': 'value'}
## {'key': 'value'}
x = {}
y = x
x['key'] = 'value'
y
## {'key': 'value'}
x.clear() ## clear the value x points to
y ## y still points to what x points to
## {}

references and values (part 2)

copy

d = {}
d['username'] = "admin"
d['machines'] = ["foo", "bar"]
d
## {'username': 'admin', 'machines': ['foo', 'bar']}
c = d.copy()
c['username'] = "Alex" ## c['username'] points to a new value
print(c)
## {'username': 'Alex', 'machines': ['foo', 'bar']}
print(d)
## {'username': 'admin', 'machines': ['foo', 'bar']}
c['machines'].remove("bar") ## references don't change, the underlying values are changed.
print(c)
## {'username': 'Alex', 'machines': ['foo']}
print(d)
## {'username': 'admin', 'machines': ['foo']}

references and values (shallow copy)

copy

from copy import deepcopy

d = {}
d['username'] = "admin"
d['machines'] = ["foo", "bar"]
d
## {'username': 'admin', 'machines': ['foo', 'bar']}
c = d.copy()
dc = deepcopy(d)
d['machines'].remove("bar") 
print(c)
## {'username': 'admin', 'machines': ['foo']}
print(dc)
## {'username': 'admin', 'machines': ['foo', 'bar']}

references and values (deep copy)

dictionary initialization: fromkeys

{}.fromkeys(["name", "age"])
## {'name': None, 'age': None}
dict.fromkeys(["name", "age"])
## {'name': None, 'age': None}
dict.fromkeys(["name", "age"], "unknown")
## {'name': 'unknown', 'age': 'unknown'}

dictionary: get

d = {"name": "Amy", "age": 24}
d["name"]
## 'Amy'
d.get("name")
## 'Amy'
d["XX"]
d.get("XX")
d.get("XX", "No exist") ## set your own return value for get

dictionary: items

phonebook = {"Alice": 2341, 
            "Beth": 4971,
            "Carl": 9401
}
phonebook
## {'Alice': 2341, 'Beth': 4971, 'Carl': 9401}
phonebook.items() ## this is an iterable
## dict_items([('Alice', 2341), ('Beth', 4971), ('Carl', 9401)])
list(phonebook.items())
## [('Alice', 2341), ('Beth', 4971), ('Carl', 9401)]

dictionary: loops

it = phonebook.items()
for key, value in it:
    print(key +  "--> " + str(value))
## Alice--> 2341
## Beth--> 4971
## Carl--> 9401
it = phonebook.items()
for _, value in it:
    print(str(value))
## 2341
## 4971
## 9401
for key in phonebook:
    print(key +  "--> " + str(phonebook[key]))
## Alice--> 2341
## Beth--> 4971
## Carl--> 9401
phonebook.values() ## this is an iterable
## dict_values([2341, 4971, 9401])
list(phonebook.values())
## [2341, 4971, 9401]
for i in phonebook.values():
    print(i)
## 2341
## 4971
## 9401

dictionary: pop and popitem

phonebook = {"Alice": 2341, 
            "Beth": 4971,
            "Carl": 9401
}
phonebook.pop("Alice")
## 2341
phonebook
## {'Beth': 4971, 'Carl': 9401}
phonebook = {"Alice": 2341, 
            "Beth": 4971,
            "Carl": 9401
}
phonebook.popitem()
## ('Carl', 9401)
phonebook
## {'Alice': 2341, 'Beth': 4971}

tuple: review basics

atuple = (0,1,2)
atuple += (3,4,5)
atuple
## (0, 1, 2, 3, 4, 5)
btuple = (0, 1, 1, ['I', 'like',  'python'])
btuple[3][0] = 'You'
print(btuple)
## (0, 1, 1, ['You', 'like', 'python'])
print(btuple.count(1))
## 2
print(btuple.index(['You', "like", 'python']))
## 3

Reference