Day 1
2080/09/02
F-strings, or formatted string literals, provide a concise way to embed expressions inside string literals in Python. You create an f-string by prefixing the string with the letter "f" or "F". Inside the string, you can include expressions enclosed in curly braces {}
. These expressions will be evaluated at runtime, and their values will be inserted into the string.
Typecasting:
Typecasting, also known as type conversion, is the process of converting a value from one data type to another.
Implicit (Auto)
Explicit (Manual)
The absolute value of a real number is its distance from zero on the number line, regardless of direction. It is always a non-negative value.
In the context of math.e
, e
refers to Euler's number, also known as the base of the natural logarithm. Euler's number is an irrational mathematical constant approximately equal to 2.71828.
Day 2
09/03
Day -3
09/05
Day -4
09/06
Day -5
09/08
Dictionaries
Imagine a real-world dictionary:
It stores words (keys) and their corresponding definitions (values).
You look up a word to find its definition quickly.
Python dictionaries work similarly:
They store key-value pairs.
You use keys to quickly access associated values.
Day -6
09/09
# Rock Paper Scissors game in python
import random
options = ("rock", "paper", "scissors")
playAgain = True
while playAgain:
player = None
computer = random.choice(options)
while player not in options:
player = input("Enter your choice 'rock', 'paper' or 'scissors': ")
print(f"Player: {player}")
print(f"Computer: {computer}")
if player == computer:
print("It's a tie")
# The or \ is a way of continuing a line of code onto the next line in Python.
elif (player == "rock" and computer == "scissors") or \
(player == "paper" and computer == "rock") or \
(player == "scissors" and computer == "paper"):
print("You win")
else:
print("You lose")
conti = input("Wanna play again? (y/n): ")
while conti != 'y' and conti != 'n':
print("Invalid entry, enter y/n:")
conti = input("Wanna play again? (y/n): ")
if conti == 'n':
playAgain = False
break
elif conti == 'y':
computer = random.choice(options)
# Encryption program in python
import random
import string
chars = " " + string.punctuation + string.digits + string.ascii_letters
chars = list(chars) #chars is typecasted into list
keys = chars.copy()
random.shuffle(keys)
# Encryption
msg = input("Enter message to encrypt: ")
cipher_text = ""
for letter in msg:
index_ = chars.index(letter)
cipher_text += keys[index_]
print(f"Text encoded: {cipher_text}")
#Decryption
original_msg = ""
cipher = input("Enter the cipher text to decode: ")
for item in cipher:
ind_ = keys.index(item)
original_msg += chars[ind_]
print(f"Original message: {original_msg}")
# function = A block of reusable code
# place ( ) after the function name to invoke it
def happy_birthday():
print("Happy Birthday")
happy_birthday()#calling function
def happy_dashain(name):
print(f"Happy Dashain {name}")
happy_dashain("Sujan")
# return = statement used to end a function and send a result back to the caller
def create_fullname(first,last):
fullname = first+" "+last
return fullname
full = create_fullname("Sujan", "Thapa")
print(f"Your full name is : {full}")
# default arguments
def volume(length, breadth = 5, height = 6):
#the values in breadth and height are default
return length*breadth*height
store = volume(2)
print(store)
store = volume(4,5,8)#but if values are provided, it will override the default
print(store)
# default arguments
import time
def timer(start, end=0):
for x in range(start,end,-1):
print(x)
time.sleep(1)
print("Done")
timer(15)
# keyword arguments = an argument preceded by an identifier
# helps with readability
# order of arguments doesn't matter
def name(name,age,country, hobby):
return {f"{name}-{age}-{country}-{hobby}"}
#positional arg must be ahead than the keyword arguments like name
store = name("Sujan",hobby="fishing", country="Nepal", age=24)
print(store)
#but in this case, we are having all keywords arg, so the order doesn't matter
store = name(hobby="reading", country="USA", age=22, name="Smith")
print(store)
print("1","2","3","4",sep="-")#print has it's own keyword arg?
# *args = allows you to pass multiple non-key arguments
# **kwargs = allows you to pass multiple keyword-arguments
def add(*args):
total = 0
for arg in args:
total += arg
return total
store = add(3,4,3,34,4,5)
print(store)
# *args = allows you to pass multiple non-key arguments (tuple)
# **kwargs = allows you to pass multiple keyword-arguments (dictionary)
def names(*args):
for arg in args:
print(arg,end=" ")
names("Sujan", "Puja", "Rohan")
# *args = allows you to pass multiple non-key arguments
# **kwargs = allows you to pass multiple keyword-arguments
# * = unpacking operator
def names(**kwargs):
for key in kwargs.keys():
print(key, end=" ")
print()
for value in kwargs.values():
print(value, end=" ")
print()
for item in kwargs.items():
print(item, end=" ")
names(name = "Sujan",
age = 24,
hobby = "fishing")
# *args = allows you to pass multiple non-key arguments
# **kwargs = allows you to pass multiple keyword-arguments
def names(*args, **kwargs):
for arg in args:
print(arg, end=" ")
print()
print(kwargs.get("name"))
print(kwargs.get("hobby"))
names("Bob", 3, "singing",
name = "Sujan",
age = 24,
hobby = "fishing")
Day -7
09/10
# module = a file containing code you want to include in your program
# use 'import' to include a module (built-in or your own)
# useful to break up a large program reusable separate files
import math #built-in module
print(math.pi)
# read write and append in python
# The second argument is read by default, w for write a for append
text = "Let's learn some Python today"
text_plus = "Yeah, that will be fun"
#This will create a new file called a.txt and write the text.
with open("D:\\a.txt",'w') as file:#with open, it closes the file as soon as it does
# it's work
file.write(text)
# We are reading the text that is just written
with open("D:\\a.txt") as f:
print(f.read())
#if we don't specify a as to append, then the previous data will be overridden
# Let's append (add) something new
with open("D:\\a.txt",'a') as fi:
fi.write(text_plus)
# We are reading the text after appending something new
with open("D:\\a.txt") as fe:
print(fe.read())
# copyfile() = copies contents of a file
# copy() = copyfile() + permission mode + destination can be a directory
# copy2() = copy() + copies metadata (file's creation and modification times)
import shutil
with open("D:\\z.txt") as file:
print(file.read())
shutil.copy("D:\\z.txt","D:\\a.txt") #src, destination
with open("D:\\a.txt") as file:
print(file.read())
# moving files in python
# same process is to move directories
import os
source = "D:\\z\\ab.txt"
destination = "D:\\anyname.txt"
# I tried doing between C and D drives but didn't work
os.replace(source,destination)# this moves the ab.txt to D:\anyname.txt the destination name
# can be whatever we want to save, in my case, anyname.txt
Day -8
09/11
# deleting files and folders in python
import os
path = "D:\\z.txt"
os.remove(path) # it removes the z.txt file
path = "D:\\anynamefolder"
os.rmdir(path)
# to delete a folder and the contents inside it
import shutil
shutil.rmtree("D:\\exfolder") # considered quite dangerous
# this is info.py file
class Info:
def __init__(self, name, age, address): # a constructor
self.name = name # it's like this.name = name
self.age = age
self.address = address
def study(self): # they're methods
print(f"{self.name} of {self.age} is studying")
def live(self):
print(f"{self.name} is living in {self.address}")
from info import Info
person1 = Info("Sujan", 24, "Pokhara")
person1.live()
person2 = Info("Smith", 20, "KTM")
person2.study()
# class and instance variables
class Info:
college = "PU"
def __init__(self, name):
self.name = name # instance variable
def say(self):
print(f"My name is {self.name}")
from info import Info
person1 = Info("Sujan")
person1.say()
print(person1.college) #Accessing class variable
Info.college = "TU" #changing the class variable
print(person1.college)
person1.college = "Other" #overrides all other?
print(person1.college)
# inheritance
class Animal:
isAlive = True
def eat(self):
print("This animal eats")
class Rabbit(Animal):
def run(self): # defining own method
print("Rabbit is running")
rabbit = Rabbit() #creating object
print(rabbit.isAlive)
rabbit.eat() #accessing the parent's method
rabbit.run() #accessing own's method
# mulit-level inheritance
class Organism:
isAlive = True
class Animal(Organism):
def eat(self):
print("Animal eats")
class Lion(Animal):
def roar(self):
print("Lion roars")
lion = Lion()
print(lion.isAlive)
lion.eat()
lion.roar()
# multiple inheritance
class Animal():
def animal(self):
print("I am animal")
class Air():
def air(self):
print("I can fly")
class Aqua():
def aqua(self):
print("I am aquatic")
class Whale(Animal, Aqua):
print("I am Whale Woooooooooooooooooo!")
class Bird(Animal, Air):
def fly(self):
print("I am a bird. FLY FLY!!")
whale = Whale() #can't access land
whale.animal()
whale.aqua()
print()
bird = Bird() #can't access to aqua
bird.fly()
bird.animal()
bird.air()
# method overriding
class Animal:
def eat(self):
print("Animal eats")
class Lion(Animal):
def eat(self):#ovveride the eat from the parent class
print("Lion eats meat")
lion = Lion()
lion.eat()# output: Lion eats meat
# method chaining = calling mutliple methods sequentially
# each call performs an action on the same object and returns self
class Car:
def start(self):
print("Car is starting")
return self
def drive(self):
print("I am driving car")
return self
def brake(self):
print("Brake is applied")
return self
def stop(self):
print("Car is stopped")
return self
car = Car()
# after car.start it returns self and then again self.other methods sequentially
# \ for continuation on the next new line
# we could also write car.start().drive().brake().stop()
car.start()\
.drive() \
.brake()\
.stop()
# super = Function used to give access to the methods of a parent class.
# Returns a temporary object of a parent class when used
# without super keyword
class Rectangle:
pass
class Square:
def __init__(self, length, breadth):
self.length = length
self.breadth = breadth
def area(self):
return self.length*self.breadth
class Cuboid:
def __init__(self, length, breadth, height):
self.length = length
self.breadth = breadth
self.height = height
def vol(self):
return self.length*self.breadth*self.height
square = Square(4,9)
print(square.area())
volume = Cuboid(5,2,9)
print(volume.vol())
# super = Function used to give access to the methods of a parent class.
# Returns a temporary object of a parent class when used
# with super keyword
class Rectangle:
def __init__(self, length, breadth):
self.length = length
self.breadth = breadth
class Square(Rectangle):
def __init__(self, length, breadth):
super().__init__(length,breadth)
def area(self):
return self.length*self.breadth
class Cuboid(Rectangle):
def __init__(self, length, breadth, height):
super().__init__(length, breadth)
self.height = height
def vol(self):
return self.length*self.breadth*self.height
sq = Square(2,88)
print(sq.area())
v = Cuboid(88,4,6)
print(v.vol())
Day 9
09/12
# Prevents a user creating an object ot that class
# compels a user to override abstract methods in a child class
# abstract class - a class which contains one or more abstract methods.
# abstract method - a method that has a declaration but does not have an implementation.
from abc import ABC, abstractmethod #abc = abstract class
class Vehicle(ABC):
@abstractmethod
def run(self):
pass
def stop(self):#this is not abstract method
print("Vehicle is stopped")
class Bike(Vehicle):
def run(self):
print("Bike is running YEAH!!")
#vehicle = Vehicle()# -> can't create object of abstract class
bike = Bike()
bike.run()
bike.stop()#we used it without the need of overriding
# objects as arguments
class Vehicle:
color = None
def changeColor(obj, rang):
obj.color = rang
v = Vehicle()
changeColor(v, "red")
print(v.color)# output: red
# objects as arg
class Dog:
def __init__(self, name):
self.name = name
def myDog(obj):
print(f"Hello {obj.name}")
obj = Dog("Kaley")
myDog(obj)# output: Hello Kaley
# Key Idea:
# 1) Focus on behavior, not explicit types: If an object "walks like a duck and quacks
# like a duck," it's considered a duck, regardless of its actual class.
# 2) Dynamic typing: Python doesn't require type declarations, so objects can change
# types during execution.
# 3) EAFP (Easier to Ask Forgiveness than Permission): Code tries to use methods or
# attributes directly, catching errors if they don't exist, rather than checking
# types beforehand.
class Duck:
def quack(self):
print("Quack!")
class Person:
def quack(self):
print("I'm imitating a duck!")
def make_it_quack(obj):
obj.quack() # Works for both Duck and Person objects
duck = Duck()
person = Person()
make_it_quack(duck) # Output: Quack!
make_it_quack(person) # Output: I'm imitating a duck!
# walrus operator :=
# new to Python 3.8
# assignment expression aka walrus operator
# It's a special operator that lets you assign a value to a variable and use
# that value in the same expression.
# The walrus operator can make code more concise and readable.
# It's especially useful in conditionals, loops, and list comprehensions.
#foods = list()
#list() is a built-in Python function specifically designed to create lists.
#while True:
# food = input("Enter the food you like (q to quit): ")
# if food == 'q':
# break
# foods.append(food)
foods = list()
while (food := input("Enter the food you like (q to quit): ")) != 'q':
foods.append(food)
# assign function to variable
say = print # assigning print function to variable 'say'
say("Hello")
def Ooh():
print("This works")
lol = Ooh()
print(lol)
# lol = Ooh()
# This calls the function named Ooh that you defined earlier.
# The function's job is to print "This works" to the console.
# However, since the function doesn't specifically return any value,
# it automatically returns None.
# So, the variable lol ends up storing this None value.
Day 10
09/13
# Higher Order Function = a function that either:
# 1. accepts a function as an argument
# or
# 2. returns a function
# (In python, functions are also treated as objects)
# Example for no. 1
def write(txt):
print("hello from write function")
def copy(f):
store = f("print")
print(store)
copy(write)
# Another example
def upper(text):
return text.upper()
def lower(text):
return text.lower()
def msg(f):
store = f("HELloo")
print(store)
msg(upper)
msg(lower)
# example for no. 2
def dividend(x):
def divisor(y):
return x/y
return divisor
store = dividend(9)#this line will have the value 9 for x and returns divisor
print(store(3))#the store here acts as a divisor -> divisor(3)
# lambda function = function written in 1 line using lambda keyword
# accepts any number of arguments, but only has one expression.
# (think of it as a shortcut)
# (useful if needed for a short period of time, throw-away)
#
# lambda parameters:expression
add = lambda x,y : x + y
print(add(4,5))
agecheck = lambda age : print("Valid") if age >= 18 else print("Not eligible")
agecheck(78)
fullname = lambda fname, lname : fname+" "+lname
print(fullname("Smile", "Please!"))
# sort() method = used with lists
# sorted() function = used with iterables
friends = ["Zion","Diken","Smith", "Bishwas", "Catrick","Rohan"]
friends.sort()# the list is sorted. Reverse? then reverse = False in the ()
for friend in friends:
print(friend)
#this time for tuples
friends = ("Zion","Diken","Smith", "Bishwas", "Catrick","Rohan")
sorted_friends = sorted(friends, reverse=True)#remove reverse for normal AZ sort
for friend in sorted_friends:
print(friend)
#sort according to the key
students = (("Squidward", "F", 60),
("Sandy", "A", 33),
("Patrick","D", 36),
("Spongebob","B", 20),
("Mr.Krabs","C", 78))
store = sorted(students)#this will sort acc. to the first coloumn
for student in store:
print(student)
print()
#sorting acc. to the second coloumn
# This line creates a lambda function (g) that takes one argument (grades) and
# returns the element at index 1 of that argument.
# In the context of the students tuple, this lambda function is designed to
# operate on each student tuple and extract the grade, which is the second
# element of each tuple.
g = lambda grades : grades[1]#second column is 1 in index.
store1 = sorted(students, key=g)
for student in store1:
print(student)
# same you can do for third column making another lambda function.
#sort according to the key
students = [("Squidward", "F", 60),
("Sandy", "A", 33),
("Patrick","D", 36),
("Spongebob","B", 20),
("Mr.Krabs","C", 78)]
g = lambda grades : grades[1]
# we are doing on list in this case
students.sort(key=g)
for student in students:
print(student)
# map() = applies a function to each item in an iterable (list, tuple, etc.)
#
# map(function,iterable)
numbers = [1,2,3,4,5]
square = map(lambda x: x*x, numbers)#could use here the list to shorten
result = list(square)
print(result)#Output: [1, 4, 9, 16, 25]
store = [("shirt",20.00),
("pants",25.00),
("jacket",50.00),
("socks",10.00)]
doguna = lambda data: (data[0], data[1]*2)
d = map(doguna,store)
result = list(d)
for item in result:
print(item)
# filter() = creates a collection of elements from an iterable,
# for which a function returns true
#
# filter(function, iterable)
friends = [("Rachel",19),
("Monica",18),
("Phoebe",17),
("Joey",16),
("Chandler",21)]
#In filter, none like in the map, you can use just one aspect?
store = lambda age : age[1]>=18#function
applyfilter = filter(store, friends)#applying filter
result = list(applyfilter)#Convert the filter object into a list
for drinkingfriend in result:#accessing friend in friends
print(drinkingfriend)
# reduce() = apply a function to an iterable and reduce it to a single cumulative value.
# performs function on first two elements and repeats process until 1 value remains
#
# reduce(function, iterable)
import functools
numbers = [1,2,3,4,5]
store = functools.reduce(lambda x,y: x+y, numbers)
print(store)
# starting from first 2 and reducing till the last one standing?
#another one
factorial = [4,5,6,7]
result = functools.reduce(lambda x,y: x*y, factorial)
print(result)
# list comprehension = a way to create a new list with less syntax
# can mimic certain lambda functions, easier to read
# list = [expression for item in iterable]
# list = [expression for item in iterable if conditional]
# list = [expression if/else for item in iterable]
square = []
for i in range(1,10):
square.append(i*i)
print(square)
#using list comprehension
square = [i*i for i in range (1,10)]
print(square)
students = [100,90,80,70,60,50,40,30,0]
store = lambda x : x > 45
passed = list(filter(store, students))
print(passed)
students = [i for i in students if i > 45]
print(students)
# dictionary comprehension = create dictionaries using an expression
# can replace for loops and certain lambda functions
#
# dictionary = {key: expression for (key,value) in iterable}
# dictionary = {key: expression for (key,value) in iterable if conditional}
# dictionary = {key: (if/else) for (key,value) in iterable}
# dictionary = {key: function(value) for (key,value) in iterable}
cities_in_F = {'New York': 32, 'Boston': 75, 'Los Angeles': 100, 'Chicago': 50}
cities_in_C = {key: round((value-39)*(5/9)) for (key,value) in cities_in_F.items()}
print(cities_in_C)
weather = {'New York': "snowing", 'Boston': "sunny", 'Los Angeles': "sunny", 'Chicago': "cloudy"}
sunny = {key: value for (key, value) in weather.items() if value == "sunny"}
print(sunny)
cities = {'New York': 32, 'Boston': 75, 'Los Angeles': 100, 'Chicago': 50}
summer = {key: ("WARM" if value>50 else "OOOOOH COLD") for (key, value) in cities.items()}
print(summer)
def check_temp(value):
if value < 70:
return "Warm"
elif 50 <= value <40:
return "Ok"
else:
return "Cold"
cities = {'New York': 32, 'Boston': 75, 'Los Angeles': 100, 'Chicago': 50}
hot = {key: check_temp(value) for (key, value) in cities.items()}
print(hot)
Output:
{'New York': -4, 'Boston': 20, 'Los Angeles': 34, 'Chicago': 6}
{'Boston': 'sunny', 'Los Angeles': 'sunny'}
{'New York': 'OOOOOH COLD', 'Boston': 'WARM', 'Los Angeles': 'WARM', 'Chicago': 'OOOOOH COLD'}
{'New York': 'Warm', 'Boston': 'Cold', 'Los Angeles': 'Cold', 'Chicago': 'Warm'}
# zip(*iterables) = aggregate elements from two or more iterables (list,
# tuples, sets, etc.)
# creates a zip object with paired elements stored in tuples
# for each element
names = ["Sujan", "Sunil","Sabin"]
numbers = (2,3,8)
result = zip(names, numbers)
print(type(result))
for item in result:
print(item)
print()
result = list(zip(names, numbers))
print(type(result))
for i in result:
print(i)
print()
result = dict(zip(names, numbers))
print(type(result))
for key,value in result.items():
print(f"{key} : {value}")
print()
age = [24, 34, 44]
store = zip(names, numbers, age)
for element in store:
print(element)