Python Course Zero to Mastery Started at Udemy Part-1

Part 2 Available in this link: Link

Python usually uses an interpreter. The compiler are a little bit different.

Interpret translates line by line.

Compiler takes all lines to machine code.

What is programming language? We give some instruction to translator. They tell the machine what to do. Translator can be interpreter or compiler.

Interpreter:

Compiler:

Python basics till numbers:

name=input('What is your name?')
print('hellllooooo '+name)


age=input("What is your age?")
print('Cool you are '+age)

#fundamentals data-type
int
float
bool
str
list
tuple
set
dict
print(2+4)
print(2-4)
print(2*4)

#classes custom types



#specialized data types
None

Double Slash in Python:

import math
result=10/3
print(result)


print(math.floor(result))


result=10//3
print(result)

/ -> float division
//-> integer division

don’t memorize which available on the documentation

String type conversation.

a=str(100)
b=int(a)
c=type(b)
print(c)

Formatted String:

#formatted strings
name='Johnny'
age=55
print(f'HI {name}. you are {age} years old')

print('HI {}: yOU ARE {} years old'.format(name,age))

String Index

#string indexes
selfish='me te ke'
       #0123456789

#[start:stop:stepover]
print(selfish[::-3])

selfish[start:stop:stepover]

Immutabilty

Built in functions
Booleans

#booleans
name='Andrei'
is_cool=False
is_cool=True
print(bool('False'))

Software to find your current age with python:

birth_year = input('what year were you born?')
birth_year=int(birth_year)
print(type(birth_year))
current_year=2021
age=abs(birth_year-current_year)
print(age)
birth_year = input('what year were you born?')
int(birth_year)
current_year=2021
age=abs(int(birth_year)-current_year)
print(age)

#1 “old style” string formatting(% operator)

#2 it is known python f string/string interpolation started from python 3.6 
name = 'bob'
print(f'hello, {name}!')

a=5
b=10
print(f'Five plus ten is {a+b}, it is not {2*(a+b)}')

Source: https://realpython.com/python-string-formatting/

Template string ta pore kokhono hoyto dekhbo, ei ar ki

password length printing code from the course:

username=input('what is your username?')
password=input('what is your password?')

password_length=len(password)
hidden_password='*'*password_length
print(f'{username}, your password {hidden_password}, is, {password_length} {len(password)} letters long')
#list
li=[1,2,3,4,5]
li2=['a','b','c']
li3=[1,2,'a', True]

amazon_cart=['notebooks','sunglass']
print(amazon_cart[1])

List

#List slicing
amazon_cart = [
'notebooks',
'sunglasses',
'toys',
'grapes'
]
#greet = 'hello'
#greet[0] = 'z' #it is immuatble but list is mutable 


amazon_cart[0]='laptop'
new_cart=amazon_cart[:] #it is copyinh amazon_cart now
new_cart[0]='gum'
print(new_cart)
print(amazon_cart)

Matrix

#matrix
matrix=[
  [1,2,3],
  [2,4,6],
  [7,8,9]
  ]

matrix=[
  [1,0,1],
  [0,1,0],
  [1,0,1]
]


print(matrix[0][1])

list operations:

basket=[1,2,3,4,5]
basket.append(100)
print(basket)

new_list=basket.append(102)
print(new_list)
print(basket)

new_list=basket.insert(2,100)
print(basket)

new_list=basket.extend([39])
print(basket)

#removing
basket.pop()
basket.pop()
basket.remove(5)
print(basket)
#removing
new_list=basket.pop(4)
print(new_list)
new_list=basket.clear()
print(basket)

we can see the function from online documentation from the official site or other sites

basket=[1,2,3,4,5]
print(basket.index(2))

basket=['a','x','b','c','d','e','d']

print('d' in basket)
print('i' in 'hi my name is Ian')
print(basket.count('d'))


#basket.sort() #it is method here
#but we can also do with method


#new_basket=basket.copy()
#new_basket.sort()
#print(sorted(basket))
basket.reverse()
print(basket)

 

basket=['a','x','b','c','d','e','d']
basket.sort()
basket.reverse()
print(basket[::-1]) ##for reversing
print(basket[:])#copy
print(basket)

 

new_sentence=' '.join(['hi', 'my', 'name', 'is', 'JOJO'])
print(new_sentence)
new_sentence=' '.join(['hi', 'my', 'name', 'is', 'JOJO'])
print(new_sentence)

 

#list unpaking
a,b,c, *other, d=[1,2,3,4,5,6,7,8,9]

print(a)
print(b)
print(c)
print(other)
print(d)
weapons=None
print(weapons)

 

#Dictionary both data structure and data type
dictionary={
    'a':[1,2,3],
    'b':'hello',
    'x':True
}


print(dictionary)

Dictionary

#Dictionary
user={
    'basket':[1,2,3],
    'greet': 'hello',
    'age': 20
}

user2=user.copy()
print(user)
print(user2)

print(user.popitem())
print(user)

print(user.update({'age':54}))
print(user)
print('size' in user)

print('age' in user.keys())

user2

Tuple:

#Tuple
my_tuple=(1,2,3,4,5)
new_tuple=my_tuple[1:4]
print(new_tuple)

x=my_tuple[0]
y=my_tuple[1]

print(x)
print(y)

x,y,z, *other=(1,2,3,4,5)
print(other)

print(my_tuple.index(5))
print(my_tuple.count(2))
print(len(my_tuple))

Set:

set is an unordered collection of unique objects.

my_set={1,2,3,4,5}
print(my_set)
my_set.add(2)
my_set.add(100)
print(my_set)

my_list=[1,2,3,4,5,5]
print(set(my_list))

my_set={1,2,3,4,5,5}
print(len(my_set))
new_set=my_set.copy()
my_set.clear()
print(new_set)
print(my_set)
my_set={1,2,3,4,5,}
your_set={4,5,6,7,8,9,10}
print(my_set.intersection(your_set))
print(my_set.isdisjoint(your_set))
print(my_set.union(your_set))
print(my_set | your_set) #it is lso union sign |
print(my_set & your_set) #intersection & sign

print(my_set.issubset(your_set))
print(my_set.issuperset(your_set))
#
# z=my_set.difference(your_set)
# print(z)
# my_set.difference_update(your_set)
# zl=my_set.discard(5)
# print(zl)

conditional.

is_old=False
is_licenced=False

if is_old:
    print('you are old enough to drive')
if is_old and is_licenced:
    print('you are old enough to drive, and you have a licence!')
elif is_licenced:
    print('You can drive now!')
else:
    print('you are not of age')

    print('okoko')

 

Truthy and Falsy:

is_old=bool('hello')
is_licenced=bool(5)

print(is_old)
print(is_licenced)

print(bool(''))
print(bool(0))

password='123'
username='johnny'

if password and username:
    print('Hello How are u?')

 

#Ternary Operator: another way to do conditional logic

#  condition_if_true if condition else confition_if_else
  is_friend=False
  can_mesage="message allowed " if is_friend else "not allowed to message"
  print(can_mesage)
  #Short Circuiting
is_Friend=True
is_User=True

if is_Friend and is_User:
    print('BEST FRIENDS FOREVER')

if is_Friend or is_User:
    print('BEST FRIENDS FOREVER')
#Logical operators:

print(4<5)
print(4==5)
#print(4=5)
print('a'>'A')
#short circuiting
print(1>=2>3<4)
print(0!=0)
#<> == >= >= !=
print(not(True))
print(not(False))

print(not(1==1))

Exercise: Logical Operators

is_magician = True
is_expert = False

# check if both magician AND expert: "you are a master magician"

if is_magician and is_expert:
    print('You are a master magician')

# check if magician but not expert: "at least you are getting there"
elif is_magician and not (is_expert):
    print('At least you are getting there')

# if you are not a magician : "You need magic powers"

elif not (is_magician):
    print('You need magic powers')

Equality

print(True==1)
print(''==1)
print([]==1)
print(10==10.0)
print([]==[])
print([1,2,3]==[1,2,3])

is vs == 
with using ‘is’ it needs to be refers to the same object

with == it needs to be equally same valued

for example:

print(True is True)
print('1'is '1')
print([] is [])
print(10 is 10.0)
print([1,2,3] is [1,2,3])

 

for teddybears in 'Zero to Mastery':
    print(teddybears)

for teddybears in (1,2,3,4,5):
    print(teddybears)
    print(teddybears)
    print(teddybears)
print('teddybears')
#list []
#set {}
#tuple ()
#dictionary user={
#    'age': 78
# }

for item in (1,2,3,4,5):
    for x in ['a', 'b', 'c']:
        print(item, x)

#iterable-list,dictionary,tuple,set,string
#those are iterable because those can be iterated -> one by one check each item in the collection

 

#users is a object
users= {
    'name':'Golem',
    'age':5006,
    'can_swim':False
}
for item in users:
    print(item)

for item in users.values():
      print(item)

for item in users.keys():
      print(item)

for item in users.items():
      print(item)
      
#items values and keys for iterating over dictionaries
# users is a object
users = {
    'name': 'Golem',
    'age': 5006,
    'can_swim': False
}
for item in users:
    print(item)

for item in users.values():
    print(item)

for item in users.keys():
    print(item)

for k,v in users.items():
    print(k,v)
#collection of item is iterable

#integer 50 is not colelction so it is not iterable
for item in 50:
    print(item)

Exercise: Counter will print item in list

#loop and then sum up the total of the list
my_list=[1,2,3,4,5,6,7,8,9,10]

count=0
for item in my_list:
    count=count+item;
print(count)

Range

print(range(100))

#range is different kinds of object

for _ in range(10,0,-1):
    print(_)

for _ in range(0,10,-1):
    print(_)

for _ in range(5):
    print(list(range(10)))

Enumerate:

#enumerate
for i,char in enumerate('hellooo'):
    print(i,char)

for i,char in enumerate((1,2,3)):
    print(i,char)

for i,char in enumerate(list(range(100))):
    print(i,char)
    if char==50:
        print(f'Index is {i}')

while

#while condition:
i=0
while i<50:
    print(i)
    break #it is for breaking the infinite loop running
i=0
while i<50:
    i=i+1
    print(i)
i=0
while i<50:
    i+=1
    print(i)
i=0
while i<50:
    print(i)
    i+=1
    break
print('Done all the work!!')
my_list=[3,2,3]
for item in my_list:
    print(item)


i=0
while i<len(my_list):
    i=i+1
    print(i)
while True:
    response=input('Say Something: ')
    if(response=='bye'):
        break

 

break, pass, continue

my_list=[1,2,3]
for item in my_list:
    print(item)
    break
    continue
    pass

print('end here')

i=0
while i<len(my_list):
    print(my_list[i])
    i += 1
    break
    continue
    pass

Exercise:

picture=[
            [0,0,0,1,0,0,0],
            [0,0,1,1,1,0,0],
            [0,1,1,1,1,1,0],
            [1,1,1,1,1,1,1],
            [0,0,0,1,0,0,0],
            [0,0,0,1,0,0,0]
    ]
fill='$'
empty=''
for row in picture:
    for pixel in row:
        if (pixel==1):
            print('*', end='')
        else:
            print(' ', end='')
    print('')

#1 iterate over picture
#if 0->print ' '
#if 1-> print *

picture=[
            [0,0,0,1,0,0,0],
            [0,0,1,1,1,0,0],
            [0,1,1,1,1,1,0],
            [1,1,1,1,1,1,1],
            [0,0,0,1,0,0,0],
            [0,0,0,1,0,0,0]
    ]
fill='$'
empty=''
for row in picture:
    for pixel in row:
        if (pixel==1):
            print('*', end='')
        else:
            print(' ', end='')
    print('')

#1 iterate over picture
#if 0->print ' '
#if 1-> print *

Exercise:

#exercise : check for duplicates in list.
some_list = ['a','b','c','b','d','m','n','n']

duplicates = []
for value in some_list:
    if some_list.count(value) > 1:
        if value not in duplicates:
            duplicates.append(value)
print(duplicates)
#functions
def say_hello():
    print('helllooooo')
say_hello()

#animals_list

animals=['cat','dog','rabbit']

animals.append('guinea pig')

print(animals)

#list to a list
wild_animals=['tigers','fox']

animals.append(wild_animals)
print(animals)

Parameters and Arguments:

#parameters /define
def say_hello(name='Darth Vader',emoji='😊'): #default parameters has been used here
    print(f'Hellooo {name} {emoji}')

# positional arguments /call/invoking
say_hello('Zaki', '😊')
say_hello('Ira', '😊')
say_hello('Emily','😊')

#keyword arguments
say_hello(emoji='😊',name='Bibi')
say_hello()

Return in python:

How it works:

without return it prints none:

def sum(num1,num2):
    num1+num2

print(sum(10,5))

 

with return it prints something that I insisted for:

def sum(num1,num2):
    return num1+num2

print(sum(10,5))

Nested Return:

def sum(num1,num2):
    def another_func(num1,num2):
        return num1+num2
    return another_func(num1,num2)

#should do one thing really well.
#should return something
total=sum(10,20)
print(total)

#issues with print and return

def sum(num1,num2):
    def another_func(num1,num2):
        return num1+num2
    return another_func(num1,num2)
    return 5    #this line will not return because we have already returned something before
    print('hello') #this line will not print because we have already returned something before

#should do one thing really well.
#should return something
total=sum(10,20)
print(total)

Exercise:

#Exercise solution:
# #1. Wrap the above code in a function called checkDriverAge(). Whenever you call this function, you will get prompted for age.
# # Notice the benefit in having checkDriverAge() instead of copying and pasting the function everytime?
def checkDriverAge():
    age = input("What is your age?")
    if int(age)<18:
        print("Sorry, you are too young to drive this car. Powering off")
    elif int(age)>18:
        print("Powering on. Enjoy the ride!")
    elif int(age)==18:
        print("Congratulations on your first year of driving. Enjoy the ride!")

checkDriverAge()


#2 #2 Instead of using the input(). Now, make the checkDriverAge() function accept an argument of age, so that if you enter:
#checkDriverAge(92);
#it returns "Powering On. Enjoy the ride!"
#also make it so that the default age is set to 0 if no argument is given.

def checkDriverAge(age=0):
    if int(age)<18:
        print("Sorry, you are too young to drive this car. Powering off")
    elif int(age)>18:
        print("Powering on. Enjoy the ride!")
    elif int(age)==18:
        print("Congratulations on your first year of driving. Enjoy the ride!")

checkDriverAge() # no argument has been given

 

#builtin functions
list()
print()
max()
min()
input()

#custom function
def some_random_stuff():
    pass

some_random_stuff()

'hellloooo'.capitalize() #method is coming while putting dot for object string hellooo
#docstring
def test(a):
    '''
    Info   #we use it to tell that the documents to others
    '''

    print(a)

test('!!!!')
help(test)

#magic method
print(test.__doc__)
# #clean code
# def is_even(num):
#     if num%2 == 0:
#         return True
#     elif num%2 != 0:
#         return False
# print(is_even(51))

#more cleaning
# def is_even(num):
#     if num%2 == 0:
#         return True
#     else:
#         return False
# print(is_even(51))


#more more cleaner
# def is_even(num):
#     if num%2 == 0:
#         return True
#     return False
# print(is_even(51))


#clean code
def is_even(num):
    return num%2 == 0

print(is_even(51))
#*args #**kwargs

# def sup_func(args):
#     return sum(args)
#
# sup_func(1,2,3,4,5)

def sup_func(name,*hoola,i='hi',**kwargs):
        print(hoola)
        print(kwargs)
        total=0
        for items in kwargs.values():
            total+=items
        return sum(hoola)+total

print(sup_func(1,2,3,4,5, num1=5, num2=10))

#Rule: params, *args, default parameters, **kwargs

#*args #**kwargs

# def sup_func(args):
#     return sum(args)
#
# sup_func(1,2,3,4,5)

def sup_func(name,*hoola,i='hi',**kwargs):
        print(hoola)
        print(kwargs)
        total=0
        for items in kwargs.values():
            total+=items
        return sum(hoola)+total

print(sup_func(1,2,3,4,5, num1=5, num2=10))

#Rule: params, *args, default parameters, **kwargs

Exercise: To find even and max value from a list

def highest_even(li):
    evens = []
    for items in li:
        if items%2 == 0:
            evens.append(items)
    return max(evens)

print(highest_even([10,2,3,4,8,11]))
#walrus operator
a = 'hellooooooo'
if ((n:=len(a))>10):
    print(f"too long {n} elements")
while(( n:= len(a))>1):
    print(n)
    a=a[:-1]
    print(a)
#scope-what variables do i have access to?
total=100
if True:
    x=10

def some_func():
    total=100

print(x)
print(type(None))
print(type(True))
print(type(5))
print(type(5.5))
print(type('hi'))
print(type([]))
print(type(()))
print(type({}))
class BigObject: #class
    pass

obj1=BigObject()#instantiate

obj2=BigObject()
obj3=BigObject()
#Everthying is an object when we use class keyword
print(type(BigObject))
print(type(obj1))
#oop learning by me
#dry=do not repeat your self
#blueprint
class PlayerCharacters:
    def __init__(self, name, age):
        self.name=name #attributes
        self.age=age

    def run(self):
        print('run')
        return 'done'
#instances
player1=PlayerCharacters('Cindy',44)
player2=PlayerCharacters('Tom',21)

print(player1.name,player1.age)
print(player2.name,player2.age)
print(player1.run())
print(player1)
print(player2)

 

Abstraction: private vs Public

class PlayerCharacter:
    def __init__(self,name,age): #__init is dunder methods
        self._name=name #private is abstraction shows _name
        self._age=age

    def run(self):
        print('run')

    def speak(self):
        print(f'my name is {self.name}, and I am {self.age} years old')

player1=PlayerCharacter('Andrei',100)


print(player1.speak())

 

Inheritance:

#users -wizard - archers -ogres
class User:
    def sign_in(self):
        print('logged in')

class Wizard(User):
    def __init__(self, name, power):
        self.name=name
        self.power=power
    def attack(self):
        print(f'attacking with power of self.power')
class Archer(User):
    def __init__(self, name, num_arrow):
        self.name=name
        self.num_arrow=num_arrow
    def attack(self):
        print(f'attacking with arrows: arrows left {self.num_arrow}')

wizard1=Wizard('Merlin', 50)
archer1=Archer('Robin',100)
wizard1.attack()
archer1.attack()

print(isinstance(wizard1, Wizard))
print(isinstance(wizard1, User))
print(isinstance(wizard1, object))
[].__repr__()
wizard1.__repr__()

Polymorphism:

#users -wizard - archers -ogres
class User:
    def sign_in(self):
        print('logged in')

class Wizard(User):
    def __init__(self, name, power):
        self.name=name
        self.power=power
    def attack(self):
        print(f'attacking with power of {self.power}')
class Archer(User):
    def __init__(self, name, num_arrow):
        self.name=name
        self.num_arrow=num_arrow
    def attack(self):
        print(f'attacking with arrows: arrows left {self.num_arrow}')

wizard1=Wizard('Merlin', 50)
archer1=Archer('Robin',100)
wizard1.attack()
archer1.attack()

print(isinstance(wizard1, Wizard))
print(isinstance(wizard1, User))
print(isinstance(wizard1, object))
[].__repr__()
wizard1.__repr__()

print(wizard1.attack())

def player_attack(char):
    char.attack()

for char in [wizard1,archer1]:
    char.attack()

 

no amount of video is enough you have to learn by your way of development projects.

4 pillars in oop Encapsulation, Abstraction, Inherítance, Polymorphism

 

Now i am looking for another video from youtube to learn something about it.

class Customer:
    def __init__(self,name,membertype):
        self.name=name
        self.membertype=membertype

        #encapsulation  with custom methods

    def update_membership(self, new_membership):
        self.membertype=new_membership

    def read_customer(self):
             print("Reading customer from DB")

# c=Customer('Zaki Live', 'Bronze')
# print(c.name,c.membertype)
#
# c2=Customer('Miranda','Golds')
# print(c2.name,c2.membertype)

customers=[Customer('Zaki Live', 'Bronze'),
           Customer('Miranda','Golds')]

print(customers[1].membertype)
customers[1].update_membership("Bronze")
print(customers[1].membertype)


# print(customers[0].name,customers[0].membertype)
# print(customers[1].name,customers[1].membertype)


#end of encapsulation

Another youtube playlist I found easy to understand really:

https://www.youtube.com/watch?v=XSoA4hwYQNw&list=PLzgPDYo_3xuk5KMe6G8HGc_BN1n3b06SV

Normal procedural code look like:

#function
def display(name):
    print("Hello",name)

#main
display("Zaki")

Code examples from this video of OOP for future reference:
Class.py

#class creation
class Person:
    def display(self):
        print("hello")
#object creation
persion1=Person()
persion1.display() #display(persion1)

inheritance.py

#inheritance, encapsulation, polymorphism
#inherite property from other class
class animal:
    def eating(self):
        print('eating')

class dog:
    def bark(self):
        print('barking')

ddd=dog()
ddd.eating()
ddd.bark()

#
# class baseclass:
#     base_class_body
#
# class deriveclass(baseclass):
#     derived_class_body

inheritance_class_init.py

class animal:
    def __init__(seolf, name):
        seolf.name=name

class dog(animal):
    def display(self):
        print(self.name)

d=dog("babydoggg")
d.display()

class_init.py

class Persons:
    def __init__(seolf,name): #self charao kaaj hoy!
        seolf.namaa=name #seolf/self instance vsriable
        #self referes to object
        #name=local variannle
        name="John"
        print(name)

    def display(seollf):
        print('hello',seollf.namaa)

p1=Persons('Poooook')
p1.display()

class_init_update.py

class Person:
    def __init__(self, name):
        self.bong=name
#self.bong is an instance variable. name is local variable
        name="Pong Pong"
        print(name)
    def display(self):
        print("Hallo!",self.bong)

person1=Person("Zaki") # here instantiating the Person class and creating object
person1.display()

#we can also write like that way too
Person("ZZAki").display()

class_und_instance_variable.py

class student:
    clg='xyz' #class variable

    def __init__(self,rollno,name):
        self.rollno=rollno
        self.name=name

    def display(llo):
        print("student name:",llo.name)
        print("student rollnumber:",llo.rollno)
        print("college:",student.clg)

student1=student('xyz001',"amul")
student1.display()

student2=student('xyz056','john')
student2.display()

student("Foi123","rrt").display()
student("Koi231","npjk").display()

class Weihnachts:
    @staticmethod
    def display():
        print("hello")

p=Weihnachts()
p.display()

class Warum:
    def pokpok(self):
        print("Joti")
Warum().pokpok()

class_inherit

class Animal:
    def eat(self):
        print("Eating..")

class Dog(Animal):
    def bark(self):
        print("bark")

dogdog=Dog()
dogdog.eat()
dogdog.bark()


class Prani:
    def __init__(self,name):
        self.name=name

class Biral(Prani):
    def display(self):
        print(self.name)

prani_biral=Biral("Kuttush")
prani_biral.display()

multilevel_inheritance.py

#base class
class Person:
    def display(self):
        print("hello this is base class Person")

#derived class 1
class Employee(Person):
     def printing(self):
         print("hello this is derived class1 Employee")

#dervided class 2
class Programmer(Employee):
    def show(self):
        print("Hello this derived class2 Programmer")

p=Programmer()
p.show()
p.printing()
p.display()

multiple_inheirtance.py

#if the new class derived from both class it is multiple inheritance
class land_animal:
    def printing(self):
        print("this animal lives on land")

class water_animal:
    def display(self):
        print("this animal lives on water")

class Frog(land_animal,water_animal):
    pass


p=Frog()
p.printing()
p.display()

Method Overriding

class A:
    def show(self):
        print('Good night')

class B(A):
    def show(self):
        print("Ghumaitesi")

b=B()
b.show()
#why we use method overriding?
#change the implementation of method in the derived class
#if you want to change something in the derived class from base class you can do that with overriding

method_overloading

#in python this concept is not available same method name but different parameters
#def average(a,b)
#def average(a,b,c)
#so to make overloading in Python we make a trick

class Student:

    def __init__(self,m1,m2):
        # self.m1=m1
        # self.m2=m2
        pass
    def sum(self,a=None,b=None,c=None):
        s=0
        if a!=None and b!=None and c!=None:
             s=a+b+c
        elif a!=None and b!=None:
            s=a+b
        else:
            s=a
        return s

s1=Student(67,56)

print(s1.sum(5,6))

 

 

Encapsulation:

class Car:
    # def __init__(self):
    #     self.__updatesoftware() #here this two underscore before method name means it is private
    def drive(self):
            print('driving')
    def __updatesoftware():
            print("updating software")

blackcar=Car()
blackcar.drive()
blackcar.__updatesoftware() #we cannot access this private method outside the class

Encapsulation_with_variables:

#private variable
class Car:
    __maxspeed = 0
    __name = ""

    def __init__(self):
        self.__maxspeed=200
        self.__name="supercar"

    def drive(self):
        print("driving")
        print(self.__name)
        print(self.__maxspeed)

    # def setspeed(self,speed):
    #     self.__maxspeed=speed
    #     print(self.__maxspeed)


redcar=Car()
redcar.drive()
redcar.__maxspeed=100
redcar.drive()
#redcar.setspeed(80)

Polymorphism:

class Dog:
    def sound(self):
        print("Vow vow..")

class Cat:
    def sound(self):
        print("meow meow")

#common interface
def makesound(animaltype):
    animaltype.sound()

dogObj=Dog()
catObj=Cat()
makesound(dogObj)
makesound(catObj)

Abstraction in Python:

from abc import ABC, abstractmethod
########## COMPUTER #############
#class which has abstract method calls abstract class
class Computer(ABC):
    @abstractmethod
    def process(self): #it is abstract method
        pass #python directly does not support abstract method,
class Laptop(Computer):
    def process(self):
        print("It's running")
class WhiteBoard:
    def write(self):
        print("It's writing")
    def process(self):
        print("It is different process from Whiteboard")
class Programmer:
    def work(self,com):
        print("Solving Bugs")
        com.process()

################## MOBILE PHONE ####################
class MobilePhone(ABC):
    @abstractmethod
    def network(self):
        pass #only declaration , no definition so it is abstract class

class Network_5g(MobilePhone):
    def network(self):
        print("O2 Network")
class LatestTechnology:
    def findOut(self):
        print("Yes it is here")
    def network(self):
        print("No no")
class NetworkLocator:
    def choose(self,mob):
        print("Choosing 1")
        mob.network()
        
# com=Computer()
# com.process()
com1=Laptop()
com2=WhiteBoard()
prog1=Programmer()
com1.process()
prog1.work(com1)
prog1.work(com2)

#an abstract class has atleast one abstract method in a class
#abstract method which does not have definition only declaration

# mob1=MobilePhone()
# mob1.network()

mob2=Network_5g()
mob2.network()
mob3=LatestTechnology()

net1=NetworkLocator()
net1.choose(mob2)
net1.choose(mob3)

Another OOP videos from ProgramIz.com:
https://www.programiz.com/python-programming/object-oriented-programming

OOP program for addition of complex number:

class Complex:
    def __init__(self, rea, imagina):
        self.real=rea
        self.imaginary=imagina

    def add(self, number):
        real=self.real+number.real
        imaginary=self.imaginary+number.imaginary
        result_addi=Complex(real, imaginary)
        return result_addi

n1=Complex(5,6) #real,imaginery number (5+6i)
n2=Complex(-4,2) #real, imaginary number (-4+2i)
result_add=n1.add(n2)
print("Real = ", result_add.real)
print("Imaginery= ", result_add.imaginary)

Perimiter of Triangle:

class Triangle:
    def __init__(self,a,b,c):
        self.a=a
        self.b=b
        self.c=c

    def calculate(self):
        peri=self.a+self.b+self.c
        return peri
    
tr1=Triangle(3,4,5)
print("Perimiter of triangle =",tr1.calculate())

method:

class Parrot:
    #instance attributes
    def __init__(self,name,age):
        self.name=name
        self.age=age

#methods are functions they use to define behaviors of an object
    #instance method
    def sing(self,song):
        return "{} sings {}".format(self.name,song)
    def dance(self):
        return "{} is now dancing".format(self.name)

#instantiating the object
blue=Parrot("Blue",15)

#calling our instance methods
print(blue.sing("Jingle Bells"))
print(blue.dance())

Inheritance:

#parent class/base class
class Bird:
    def __init__(self,color):
        self.color=color
        print("Bird is ready")
    def whoisthis(self):
        print("Bird")
    def swim(self):
        print("Swim faster")

#child/inherited class
class Penguin(Bird):
    def __init__(self,color):
        super().__init__(color)
        print("Penguin is ready")
        print("Penguin is {}".format(color))

    def whoisthis(self):
        print("Penguin")

    def run(self):
        print("Run faster")

peggy=Penguin("Black")
peggy.whoisthis()
peggy.swim()
peggy.run()

Inheritance with ostrich:

#parent class/base class
class Bird:
    def __init__(self, color):
        print("Bird is ready")
    def whoisthis(self):
        print("Bird")
    def swim(self):
        print("Swim faster")

#child/inherited class
class Penguin(Bird):
    def __init__(self, color):
        self.color = color
        super().__init__(color)
        print("Penguin is ready")
        print("Penguin is {}".format(color))

    def whoisthis(self):
        print("Penguin")

    def run(self):
        print("Run faster")

class Ostrich(Bird):
    def __init__(self,color):
        super().__init__(color) #with this super we can run __init__ method parent class inside child class
        self.color=color

    def whoisthis(self):
        print("Ostricch")
        print("Utpakhi with {} color !".format(self.color))

peggy=Penguin("Black")
peggy.whoisthis()
peggy.swim()
peggy.run()

utpakhi=Ostrich("Golden")
utpakhi.whoisthis()
utpakhi.swim()

Inheritance example again:

class Animal:
    def eat(self):
        print("I can eat")

class Dog(Animal):
    def bark(self):
        print("I can bark")

class Cat(Animal):
    def get_grumpy(self):
        print("I am getting grumpy")

dog1=Dog()
dog1.bark()
dog1.eat()

cat1=Cat()
cat1.eat()
class Polygon:
    def __init__(self,sides):
        self.sides=sides

    def display_info(self):
        print("A perimiter is a two dimensional shape with straight lines")

    def get_perimiter(self):
        perimeter=sum(self.sides)
        return perimeter

class Triangle(Polygon):
    def display_info(self):
        print("A triangle is a polygomn with 3 edges")
        Polygon.display_info(self)
        super().display_info() #super is an object of Polygon, we can access the method of parent class inside child class

class Quadrlateral(Polygon):
    def display_info(self):
        print("A quadrliateral is a polygon with 4 edges")
        Polygon.display_info(self)
        super().display_info()

t1=Triangle([5,6,7])
perimeter=t1.get_perimiter()
print("The perimeter is",perimeter)
t1.display_info()

q1=Quadrlateral([4,5,7,8])
perimeter=q1.get_perimiter()
print("The perimeter for quad",perimeter)
q1.display_info()
import math
class Polygon:
    def __init__(self, no_of_sides):
        self.sides_num=no_of_sides
        self.sides= [0 for i in range(self.sides_num)] #ei type er code ta notun dekhlam pore bujhte hobe

    def inputSides(self):
        self.sides=[float(input("Enter side "+str(i+1)+":")) for i in range(self.sides_num)]

    def dispSides(self):
        for i in range(self.sides_num):
            print("Side",i+1,"is",self.sides[i])


class Triangle(Polygon):
    def __init__(self):
        Polygon.__init__(self,3)

    def findArea(self):
        a,b,c=self.sides
        #calculate the semi-perimeter
        s=(a+b+c)/2
        area=(s*(s-a)*(s-b)*(s-c))**0.5
        print("The area of the triangle is %0.2f" %area)

class Quadrilateral(Polygon):
    def __init__(self):
        super().__init__(4)

    def findArea(self):
        a,b,c,d=self.sides
        #s=a+b+c+d/2
        area=(0.5*a*d)*math.sin(80)+(0.5*b*c)*math.sin(110)
        print("The area of Quad is: %0.2f"%area)
# t=Triangle()
# t.inputSides()
# t.dispSides()
# t.findArea()
q=Quadrilateral()
# q.inputSides()
# q.dispSides()
# q.findArea()
isinstance(q,Quadrilateral)

 

Encapsulation:

class Computer:
    def __init__(self):
        self.__maxprice=900
        #self.__maxprice=price

    def sell(self):
        print("Selling price {}".format(self.__maxprice))

    def setMaxPrice(self,price):
        self.__maxprice=price

c=Computer()
c.sell()

c.setMaxPrice(1000)
c.sell()

Polymorphism:

class Parrot:
    def fly(self):
        print("Parrot can fly")
    def swim(self):
        print("Parrot cannot swim")

class Penguin:
    def fly(self):
        print("Penguin cannot fly")
    def swim(self):
        print("Penguin can swim")

def flying_test(bird):
    bird.fly()
def swim_test(bird):
    bird.swim()

parrot=Parrot()
flying_test(parrot)
penguin=Penguin()
flying_test(penguin)

swim_test(parrot)
swim_test(penguin)

Some of the advanced topics from Programiz.com, they have very good written and video content there:

 

 

 

 

Now the exercise from the udemy course:

Super,Object Introspection, Dunder/Magic method

1st example:

#super, object introspection and Dunder method
class User(object):
    def __init__(self,email):
        self.email=email

    def sign_in(self):
        print('logged in')
class Wizard(User):
    def __init__(self,name,power,email):
        super().__init__(email)
        #User.__init__(self, email)
        self.name=name
        self.power=power

    def attack(self):
        print(f'{self.name} attacking with power of {self.power} ')

wizard1=Wizard('Merlin', 60, 'merlin20@gmail.com')
print(wizard1.attack())
print(wizard1.email)
#object introspection
print(dir(wizard1))

class Toy():
    def __init__(self,color,age):
        self.color=color
        self.age=age

    def __str__(self):
        return f'{self.color}'

    def __len__(self):
        return 5
    def __del__(self):
        print('deleted')
    def __call__(self):
        return('Yesss???')

action_figure=Toy('red',0)
print(action_figure.__str__())#Dunder method
print(str(action_figure))
print(len(action_figure))
del action_figure
print(action_figure.__call__())

 

2nd example:

class Toy():
    def __init__(self,color,age):
        self.color=color
        self.age=age
        self.my_dict={
            'name': 'Yoyo',
            'has_pets': False
        }

    def __str__(self):
        return f'{self.color}'

    def __len__(self):
        return 5
    def __del__(self):
        print('deleted')
    def __call__(self):
        return('Yesss???')

    def __getitem__(self, i):
        return self.my_dict[i]

action_figure=Toy('red',0)
print(action_figure.__str__())#Dunder method
print(str(action_figure))
print(len(action_figure))

print(action_figure['name'])
print(action_figure.__call__())
del action_figure

 

#modify the builtin classes/custom dunder/magic method
class SuperList(list):
    def __len__(self):
        return 1000

super_list1=SuperList();
print(len(super_list1))
super_list1.append(5)
print(super_list1[0])
print(issubclass(SuperList,object))

#Multiple Inheritance

#multiple inheritance
class User():
    def sign_in(self):
        return(f'logged in')

class Wizard(User):
    def __init__(self,name,power):
        self.name=name
        self.power=power

    def attack(self):
        return(f'Attacking with power of {self.power}')


class Archer(User):
    def __init__(self,name,arrows):
        self.name=name
        self.arrows=arrows

    def check_arrows(self):
        return(f'{self.arrows} remaining')

    def run(self):
        return('ran really fast')

class HybridBord(Wizard,Archer): #multiple inheritance check here calling two another class
    def __init__(self,name,power,arrows):
        Archer.__init__(self,name,arrows)
        Wizard.__init__(self,power,arrows)


hb1=HybridBord('borgie',50,100)
print(hb1.sign_in())
print(hb1.run())
print(hb1.check_arrows())
print(hb1.attack())

#Method Resolution Order(MRO)

#Method Resolution Order(MRO)
class A:
    #num=10
    pass
class B(A):
    pass
    #num=59
class C(A):
    #num=1
    pass
class D(B,C):
    pass

print(D.mro())
#print(D.num)
D.__str__ #WE ARE USING DUNDER STRING


Output:
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
class X:pass
class Y:pass
class Z:pass
class A(X,Y):pass
class B(Y,Z):pass
class M(B,A,Z):pass
M.mro()
print(M.__mro__) #mro string same output as the prevoious line

Output:

(<class '__main__.M'>, <class '__main__.B'>, <class '__main__.A'>,
 <class '__main__.X'>, <class '__main__.Y'>, <class '__main__.Z'>, <class 'object'>)

Pure Function

#without outside effects
def multiply_by2(li):
    new_list=[]
    for item in li:
        new_list.append(item*2)
    return new_list

print(multiply_by2([1,2,3]))

#with outside effects
def multiply_by2(li):
    new_list=[]
    for item in li:
        new_list.append(item*2)
    return print(new_list)

multiply_by2([1,2,3])

new_list=[] #it is list but effected by empty string
def multiply_by2(li):
    for item in li:
        new_list.append(item*2)
    return print(new_list)
new_list='' #empty string,
multiply_by2([1,2,3])

#another example
wizard  = {
    'name': 'Merlin',   #this is separated so if there any bug it will not effect the pure function
    'power': 50
}

def attack(character):
    new_list=[]
    for item in character:
        new_list.append(item*2)
    return new_list

print(multiply_by2([1,2,3]))

#we always need to write pure function which does effected by outside world

 

Map()

#map, #filter, #zip and reduce

#map structure for writing codes
# map(fun,iter) where fun=it is a function wheich passes each elements of given iterable and iter = iterable which needs to be mapped

def multiply_by2(item):
    return item*2

numbers1=[1,2,3]
results1=map(multiply_by2, numbers1)
print(list(results1))


#a simple python program for map
#return double of n
def addition(n):
    return n+n
#we double all numbers using map()
numbers=(1,2,3,4)
result=map(addition,numbers)
print(list(result))

filter()

my_list=[1,2,3]
def only_odd(item):
      return item%2!=0

result=filter(only_odd,my_list)
print(list(result))

zip()

my_list=[1,2,3]
your_list=(10,20,30)
their_list=[5,4,3]
print(list(zip(my_list,your_list,their_list)))

output: [(1, 10, 5), (2, 20, 4), (3, 30, 3)]

reduce() function and how it works in python:

I have seen two videos here from udemy and youtube to clear this concept for me

code from udemy:

reduce()

from functools import reduce
my_list = [1,2,3]
def accumulator(acc,item):
    print(acc, item) # to show how it is going
    return acc+item
print(reduce(accumulator,my_list,0)) #we are starting from 0 to iterate
print(reduce(accumulator,my_list,10)) #we are starting from 10 to iterate

Output:

0 1
1 2
3 3
6
10 1
11 2
13 3
16

Exercise solutions here in function:

#1 Capitalize all of the pet names and print the list

my_pets = ['sisi', 'bibi', 'titi', 'carla']

def capiFunc(string):
    return string.upper()
print(list(map(capiFunc,my_pets)))

output:

['SISI', 'BIBI', 'TITI', 'CARLA']

#2 Zip the 2 lists into a list of tuples, but sort the numbers from lowest to highest.

my_strings = ['a', 'b', 'c', 'd', 'e']
my_numbers = [5,4,3,2,1]
list_number_new=sorted(my_numbers)
print(list(zip(my_strings,list_number_new)))

#3 Filter the scores that pass over 50%

scores = [73, 20, 65, 19, 76, 100, 88]
def morethan50(item):
    return item>50
print(list(filter(morethan50,scores)))

#4 Combine all of the numbers that are in a list on this file using reduce (my_numbers and scores). What is the total?

def addition(accu,item):
    return accu+item
print(reduce(addition,(my_numbers+scores),0))

Output:

456

Lambda Expressions in python:

Lambda is a computer science term. Which is an anonymous function. Which don’t use more than once for a purpose. Usually in lambda we don’t need to decalre any function name. What happens inside a function we can write in simple line using lambda function.

lambda using map:

#lambda expressions
numbers=[1,2,3]
# def multiply_by2(item):
#     return item*2

#print(list(map(multiply_by2, numbers)))
print(list(map(lambda item: item*2, numbers))) # this line will be forgtten after run lambda param: action(param)

lambda using filter:

#lambda expressions
numbers=[1,2,3]
print(list(filter(lambda item: item%2!=0, numbers))) # this line will be forgtten after run lambda param: action(param)

lambda using reduce:

#lambda expressions
from functools import reduce
numbers=[1,2,3]
print(reduce(lambda acc,item: acc+item, numbers)) # this line will be forgtten after run lambda param: action(param)

# Exercises using lambda
1. make a lambda example to squre

my_list=[5,4,3]
print(list(map(lambda item:item**2,my_list)))

2. make a lambda example to make a sorted list

a=[(0,2),(4,3),(9,9),(10,-1)]
print(list(filter(lambda item:sorted(a),a)))

a.sort(key=lambda x:x[1])
print(a)

List Comprehension

#list, comprehension
my_list=[]
for char in 'hello':
    my_list.append(char)

print(my_list)

#another rule with list comprehension using like that format below
#my_list=[param for param in iterable]
my_list=[char for char in 'hello']
my_list2=[num for num in range(0,100)]
my_list3=[num**2 for num in range(0,100)]
my_list4=[num**2 for num in range(0,100) if num%2==0]
print(my_list)
print(my_list2)
print(my_list3)
print(my_list4)

Set and Dict Comprehension:

#set only allow numbers
# set only allow unique numbers or characters that is why out put has only once in 
my_list={char for char in 'hello'}
my_list2={num for num in range(0,100)}
my_list3={num**2 for num in range (0,100)}
my_list4={num**2 for num in range (0,100)}
print(my_list)
print(my_list2)
print(my_list3)
print(my_list4)

#dict comprehension

#dict comprehension
simple_dict={
    'a':1,
    'b':2
}

#my_dict={key:value**2 for key,value in simple_dict.items()}
my_dict={k:v**2 for k,v in simple_dict.items() if v%2==0} #another way
my_dict1={num:num**2 for num in [1,2,3]} #different way to print dict
print(my_dict)
print(my_dict1)

Comprehension is for shorthand.

Now a small exercise:

Problem: to write a one line code to find duplicate character to show in a answer
Soln code:

some_list=['a','b','c','d','b','m','n','n']
duplicates=[]
# for value in some_list:
#     if some_list.count(value)>1:
#         if value not in duplicates:
#             duplicates.append(value)
duplicates=list(set([x for x in some_list if some_list.count(x)>1]))
print(duplicates)

Output:

['b', 'n']

Decorators:

#decorators @classmethod @staticmethod it is start with @ sign
def hello():
    print('hellllooooo');

greet = hello
del hello #keywords del delete the function

print(greet())

another example:

#decorators @classmethod @staticmethod it is start with @ sign
def hello(func):
    func()

def greet():
    print('still here')

a=hello(greet)

print(a)

Higher Order Function HOC

#higher order function(HOC)
def greet(func):
    func()
    
#filter(),map(),reduce(), all are higher order function
def greet2():
    def func():
        return 5
    return func

the decorator can supercharge the function and can add an extra feature

Decorator:

#decorator

def my_decorator(func):
    def wrap_func():
        print('******')
        func()
        print('******')
    return wrap_func

@my_decorator
def hello():
    print('helllooooo')

@my_decorator
def bye():
    print('Tschüß, see you later')

# hello()
# bye()

# a=my_decorator(hello)
# a()

# my_decorator(hello)()

Another example:

#Decorator
def my_decorator(func):
    def wrap_func(*args,**kwargs):
        print('*****')
        func(*args,**kwargs)
        print('*****')
    return wrap_func

@my_decorator
def hello(greeting, emoji=':('):
    print(greeting, emoji)

hello('hiii')

# a= my_decorator(hello)
# a('hiii',':)')
# hello('Hiii')

Practical Application of Decorator:

from time import time

def performance_time(fn):
	def wrapper(*args, **kwargs):
		t1=time()
		result=fn(*args,**kwargs)
		t2=time()
		print(f'took {t2-t1} seconds')
		return result
	return wrapper
	
@performance_time
def long_time():
	for i in range(100000000):
		i*5
		
long_time()

Another decorator example from ProgramIZ.com:

def star(func):
    def inner(*args, **kwargs):
        print("*" * 30)
        func(*args,**kwargs)
        print("*" * 30)
    return inner

def percent(func):
    def inner(*args,**kwargs):
        print("%"*30)
        #func(*args,**kwargs)
        print("%"*30)
    return inner

@star
#@percent
def printer(msg):
    print(msg)

printer("Hello")

Without Property decorator:

class Student:
    def __init__(self,marks):
        self.__marks=marks #we made the marks private variable so we need here encapsulated thing
    def per(self): #it is percentage method, it calculates percentage of given marks
        return (self.__marks/600)*100
    def setter(self, value):
        self.__marks=value
    def getter(self):
        return self.__marks

s=Student(400)
#s.marks=500
s.setter(500)
#print(s.marks)
print(s.getter())
print(s.per(),"%")

 

With Property Decorator and method:

class Student:
    def __init__(self,marks):
        self.__marks=marks #we made the marks private variable so we need here encapsulated thing
    def per(self): #it is percentage method, it calculates percentage of given marks
        return (self.__marks/600)*100

    #@property
    def getter(self):
        print("getting value:",end=" ")
        return self.__marks
   #@marks.setter
    def setter(self, value):
        if value<0 or value>600:
            print("can't set value stick to previous value!!!")
        else:
            print("setting value:",value)
            self.__marks=value
    marks=property(getter,setter)

s=Student(400)
s.marks=601
print(s.marks)
print(s.per(),"%")

Reference for property: https://www.youtube.com/watch?v=yAuCp2aZUEI

Exercise:

Need to do later as it is not downloading on my tablet

Error Handling:

# print(1+'hello')
# #error handling
# def hoooohooo():
#     pass
#     1+name
#     di={'a':1}
#     5/num
#syntax error
#error handling
while True:
    try: #the asking
        age=int(input('what is your age?'))
        #print(age)
        10/age #it is buggy if we give age 0
    except ValueError: #if there is error do this
        print('Please enter a number')
    except ZeroDivisionError:
        print('Please enter age higher than 0')

    else: #if there is no error do this
        print('Thank you')
        break

error:

#error handling
def sum(num1,num2):
    try:
        return num1+num2
    # except TypeError as err:
    #     print(f'Something is wrong {err}')
    #     print(err)
    except(TypeError,ZeroDivisionError) as err:
        print('oops!')
        print(err)

print(sum(1,'2'))
while True:
    try:
        age=int(input('What is your age?'))
        99/age
    except ValueError:
        print('Please enter a number')
        #continue
    except ZeroDivisionError:
        print('Please enter age higher than 0')
        break
    else:
        print('thank you!')
        break
    finally:
        print('ok, i am finally done')
    print('can you hear me?')

custom error in error handling:

while True:
    try:
        age=int(input('What is your age?'))
        99/age
        #raise ValueError('Hey cut it out!')
        raise Exception('Hey cut it out!')
    except ZeroDivisionError:
        print('Please enter age higher than 0')
        #break
    else:
        print('thank you!')
       # break
    finally:
        print('ok, i am finally done')
    print('can you hear me?')

Iterator:

iterators_infinite.py

class InfIter:
    """Infinite iterator to return all odd numbers"""
    def __iter__(self):
        self.num=1
        return self

    def __next__(self):
        num = self.num
        self.num+=2
        return num


a = iter(InfIter())
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))

iterator_fibonacci

class iterate_fibonacci():
    def __init__(self,max):
        self.n1=0
        self.n2=1
        self.max=max

    def __iter__(self):
        return self

    def __next__(self):
       while self.n1<=self.max:
            result=self.n1
            self.n1 = self.n2
            self.n2=self.n1+self.n2
            return result
       else:
           raise StopIteration

numbers=iterate_fibonacci(6)
print(next(numbers))
print(next(numbers))
print(next(numbers))
print(next(numbers))
print(next(numbers))

iterator power

class PowTwo():
    def __init__(self, max=0):
        self.max=max

    def __iter__(self):
        self.n=0
        return self

    def __next__(self):
        if self.n<=self.max:
            result=2**self.n
            self.n+=1
            return result
        else:
            raise StopIteration
#create an object
numbers=PowTwo(3)
#create an iterable from the object
i=iter(numbers)

#using next to get to next iterastor element
print(next(i))
print(next(i))
print(next(i))
print(next(i))
class PowTwo():
    def __init__(self, max=0):
        self.max=max

    def __iter__(self):
        self.n=0
        return self

    def __next__(self):
        if self.n<self.max:
            result=2**self.n
            self.n+=1
            return result
        else:
            raise StopIteration
#create an object
numbers=PowTwo(3)
#create an iterable from the object
i=iter(numbers)

#using next to get to next iterastor element
print(next(i))
print(next(i))
print(next(i))
print(next(i))

iterator even

class Even:
    def __init__(self,max):
        self.n=2
        self.max=max

    def __iter__(self):
        return self

    def __next__(self):
        if self.n<=self.max:
            result=self.n
            self.n+=2
            return result
        else:
            raise StopIteration

numbers=Even(10)
print(next(numbers))
print(next(numbers))
print(next(numbers))

iterator loop

num_list=[1,4,9]
iter_obj=iter(num_list)

while(True):
    try:
        element=next(iter_obj)
        print(element)
    except StopIteration:
        break

iterator infinite

class InfIter:
    """Infinite iterator to return all odd numbers"""
    def __iter__(self):
        self.num=1
        return self

    def __next__(self):
        num = self.num
        self.num+=2
        return num


a = iter(InfIter())
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))

iterator.py

numbers=[1,4,9]
value=iter(numbers)

# value=numbers.__iter__()
# print(value)
#
# numbers=[1,4,9]
# value=numbers.__iter__()


item1=value.__next__()
print(item1)

item2=value.__next__()
print(item2)

item3=value.__next__()
print(item3)

item4=next(value)
print(item4)

 

 

Generators:
Range is a generator. Generator is special type in python

generator is iterable but all iterable is not generator
example: range is generator that is always iterable, list is also iterable but not generator

generate fibonacci

def generate_fibonacci():
    n1=0
    n2=1
    while True:
        yield n1
        n1,n2=n2,n1+n2

seq=generate_fibonacci()

print(next(seq))
print(next(seq))
print(next(seq))
print(next(seq))
print(next(seq))
print(next(seq))
print(next(seq))
print(next(seq))
print(next(seq))

generator_odd.py

def odd_generator():
    n=1
    while(5!=0): #while True is infinite loops
        yield n
        n+=2

numbers=odd_generator()

for i in range(10):
    print(next(numbers))

# print(next(numbers))
# print(next(numbers))
# print(next(numbers))
# print(next(numbers))
# print(next(numbers))
# print(next(numbers))
# print(next(numbers))

generator_even

def even_generator(max):
    n=2
    while(n<=max):
        yield n
        n+=2

    # n=0
    # n+=2
    # yield n
    #
    # n+=2
    # yield n
    #
    # n+=2
    # yield n
numbers=even_generator(6)

print(next(numbers))
print(next(numbers))
print(next(numbers))

generator in loop

def rev_str(my_str):
    length=len(my_str)
    for i in range(length -1, -1, -1): #https://artofproblemsolving.com/wiki/index.php/Range_function
        yield my_str[i]
#for loop to reverse the strings
for char in rev_str("hello"):
    print(char)

generator check:

# A simple generator function
def my_gen():
    n = 1
    print('This is printed first')
    # Generator function contains yield statements
    yield n

    n += 1
    print('This is printed second')
    yield n

    n += 1
    print('This is printed at last')
    yield n


# Using for loop
for item in my_gen():
    print(item)

Python closures:

def make_multiplier_of(n):
    def multiplier(x):
        return x*n
    return multiplier

times3=make_multiplier_of(3)
print(times3(9))

times5=make_multiplier_of(5)
print(times5(3))

print(times5(times3(2)))

basic way format :

def print_msg(msg):
    #this is the outer enclosing functional
    def printer():
        #this is the nested function
        print(msg)
    #printer()
    return printer

print_msg("Hello")

another=print_msg("Hello")
another()

 

Modules:

import shopping.shopping_cart
import utility

print(shopping.shopping_cart.buy('Gorur Mangsho','Murgir Mangsho','Biriyani'))
def buy(*item):
    cart=[]
    cart.append(item)
    return cart

Some examples of using modules here:
utility.py : in this file I put all the functions for opertions

def multiply(num1, num2):
    return num1*num2


def divide(num1, num2):
    return num1/num2

Now I am sending values to those function using main :

import utility

print("Divide")
print(utility.divide(4,2))
print("Multiply")
print(utility.multiply(2,3))

 

Again another way:
main_buy.py:

import shopping_cart
#import shopping.shopping_cart //here shopping is packages and shopping_cart is module


print(shopping_cart.buy("Goru"))
#print(shopping.shopping_cart.buy("Goru"))

shopping_cart.py:

def buy(item):
    cart=[]
    cart.append(item)
    return cart

The thing need to remember usually in a package automatically a file __init__.py creates.

Another important thing a successful program without error run with exit code 0
And with error run with exit code 1

Another way of example:

main.py

from utility import multiply,divide
#from utility import *
from shopping.more_shopping.shopping_cart import buy

print(buy('apple'))
print(divide(5,2))
print(multiply(5,2))
print(max([1,2,3]))

utility.py

def multiply(num1, num2):
    return num1*num2


def divide(num1, num2):
    return num1/num2

def max():
    return 'oops'

shopping_cart.py

def buy(*item):
    cart=[]
    cart.append(item)
    return cart

 

__name__:
Again example with names:

__name__

print(__name__)
#if __name__==’__main__’:

why it is used in code, here i found a logical explanation.
link: https://s1s1ty.medium.com/concept-behind-if-name-main-in-python-fbf834d244ee

the code i applied from that link to here.

a.py

def add(x,y):
    return x+y

print(add(10,10))

if __name__=='__main__':
    print(add(4,1))

b.py

from a import add
print(add(100,1))

 

 

test.py:

from utility import multiply,divide
import utility
print(type(utility.st1))

#from utility import *
from shopping.more_shopping.shopping_cart import buy
if __name__=='__main__':
    print(buy('apple'))
    print(divide(5,2))
    print(multiply(5,2))
    print(max([1,2,3]))

#print(__name__)

   # print('please run this')

utility.py

def multiply(num1, num2):
    return num1*num2


def divide(num1, num2):
    return num1/num2

def max():
    return 'oops'

class Student():
    pass

st1=Student()
print(type(st1))

Python Built in Modules:

In other language it is known as standard library.
You don’t need to remember all, just know it exists and google it when needful.

https://docs.python.org/3/py-modindex.html

import random

#print(random)
#help(random)
#print(dir(random.))

#print(random.randint(1, 10))
#print(random.choice([1,2,3,4,5,6]))
my_list=[1,2,3,4,5]
random.shuffle(my_list)
print(my_list)


from random import shuffle
#import random as oulala

my_list=[1,2,3,4,5]
shuffle(my_list)
print(my_list)

Exercise:

#generate a number 1~10
from random import randint

answer=randint(1,10)


#input from user?

#check that input is a number 1~10
while True:
    try:
        guess = input('guess a number between 1~10:')
        if int(guess) >= 1 and int(guess) <= 10:
            print('It is all good')
            break
        else:
            print('Hey bojo, it is wrong one')

    except ValueError:
	    print('Please enter a number')
    continue

#check if number is the right guess. otherwise ask again.


for python library we can use bulit in library or third party library that is available on  pypi.org. for example: email, pdf etc.

File handling in Python:

Reading- reading when file exist code= ‘r
Writing – writing write content in the file code= ‘w’
it will be create a file
Appending -add contents to the file and no overwrite code = ‘a’

Some python code and screenshot with pycharm_
fileobject=0pen(“name of the file”,”mode of the file”)
fileobject.methodname()
method name can be read write append etc.


code:

filehandler=open("xyz.txt","a")
#print(filehandler.read())
#text="welcome to write mode of the file"
#filehandler.write(text)
text="\n appended data"
filehandler.write(text)

this two youtube video helped me to learn in details than udemy video:

 

Why we use seek in opening file and how to use it ?
Because the open is only usable once but after that to open the same thing several times we need seek()

example:

filehandler=open("xyz.txt")
print(filehandler.read())
filehandler.seek(0)
print(filehandler.read())
filehandler.seek(0)
print(filehandler.read())
filehandler.seek(0)
print(filehandler.read())
filehandler.seek(0)

another one to read all three lines at once:

filehandler=open("3lines.txt")
print(filehandler.readline())
print(filehandler.readline())
print(filehandler.readline())
#print(filehandler.readlines())
filehandler.close()

3lines.txt

Hello how are you ?
:)
Zaaaaakkiiiii

Another example of writing, one thing is r+ means read and write both.

with open('test.txt', mode='w') as my_file:
    text=my_file.write(':)')
    print(text)

Path are two types in a python system:

Absolute path and Relative path:

File Input output error:

try:
with open('sad.txt', mode='r') as my_file:
print(my_file.read())
except FileNotFoundError as err:
print('file does not exist')
#raise err ;to know about what is the error
except IOError as err:
print('It is IO error')
raise err

Debugging in Python:

#pythondeugger/pdb

import pdb
def add(num1, num2):
    pdb.set_trace()
    t=4*5
    return num1+num2
add(4,'hhhdfdv')

Output in run:

C:\Users\Zaki\PycharmProjects\modules\venv\Scripts\python.exe C:/Users/Zaki/PycharmProjects/modules/debugging_learn/main.py
> c:\users\zaki\pycharmprojects\modules\debugging_learn\main.py(16)add()
-> t=4*5
(Pdb) a
num1 = 4
num2 = 5
(Pdb) num2='dffdf'
(Pdb) next
> c:\users\zaki\pycharmprojects\modules\debugging_learn\main.py(17)add()
-> return num1+num2
(Pdb) next
TypeError: unsupported operand type(s) for +: 'int' and 'str'
> c:\users\zaki\pycharmprojects\modules\debugging_learn\main.py(17)add()
-> return num1+num2
(Pdb)

PIP Install in Pycharm on Windows environment:
pip install package-name
In below terminal not in python console

from translate import Translator
translator=Translator(to_lang='bn')

try:
    with open('test.txt', mode='r') as my_file:
        text=my_file.read()
        translation = translator.translate(text)
       # print(translation)
        with open('test-save.txt', mode='w', encoding='utf-8') as my_file2:
            my_file2.write(translation)


except FileNotFoundError as e:
    print('Please check the file path dear user :)')

 

Python Job Tricks:
– Show you have real experience by building projects

Regular Expressions:
Regular expressions are langauge independent. It is also available in other languages. It needful to check validation of words.

import re

string='search inside of this text please'

print(re.search('this',string))

out put:

span=(17, 21)

it means that ‘this’ start at span 17 and ended in span 21

Nobody remembers regex we learn it when needful. We learn later by email and password checker making.

Regex from Prgramiz.com:
I found this link as like textbook for learning regex: https://www.programiz.com/python-programming/regex

import re

pattern='^..' #'^a...s$'
test_string='ad'#'abyss'
result=re.match(pattern,test_string)

if result:
	print("Search successful")
else:
	print("Search unsuccessful")

Also some problems related to string or list can be found here : https://www.programiz.com/python-programming/examples

No one ask you in interview about Regex. So you just know how to do it.

This interactive tutorial has been suggested by Androe: https://regexone.com/lesson/wildcards_dot

import re #re means regular expressions

pattern=re.compile(r"[a-zA-Z].([a])")
string='search this inside of this text please this'

a=pattern.search(string)
b=pattern.findall(string)
c=pattern.fullmatch(string)
d=pattern.match(string)
#print(a.span())
# print(a.start())
# print(a.end())
# print(a.group())
print(b)
print(c)
print(d)

Now adding with another code for email validation:

import re #re means regular expressions

pattern=re.compile(r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)")
string='Andrei'

a=pattern.search(string)
print(a)

Password validation:

import re #re means regular expressions

pattern=re.compile(r"^(?=.*?[A-Z])(?=(.*[a-z]){1,})(?=(.*[\d]){1,})(?=(.*[\W]){1,})(?!.*\s).{8,}$")
string='Andreidsds'
pattern2=re.compile(r"[A-Za-z0-9$%#@]{8,}\d")
password='hdjk'

a=pattern.search(string)
check=pattern2.fullmatch(password)
print(check)

Testing:

#pylint
#pyflakes
#PEP8

Testing is not only in python but also for all others platform

We are learning unittesting in this section:
script.py

def do_stuff(num=0):
    try:
        if num:
            return int(num)+5
        else:
            return 'please enter number'
    except ValueError as err:
        return err

test.py

import unittest
import script

class TestMain(unittest.TestCase):
    def setUp(self):
        print('about to test a function')
    def test_do_stuff(self):
        '''

        Hiiii!!
        '''
        test_param = 10
        result = script.do_stuff(test_param)
        self.assertEqual(result, 15)

    def test_do_stuff2(self):
        test_param = 'shkshs'
        result = script.do_stuff(test_param)
        self.assertIsinstance(result, ValueError)

    def test_do_stuff3(self):
        test_param = None
        result = script.do_stuff(test_param)
        self.assertEqual(result, 'please enter a number')

    def test_do_stuff4(self):
        test_param=''
        result=script.do_stuff(test_param)
        self.assertEqual(result, 'please enter a ')

    def tearDown(self) :
        print('cleaning up')
unittest.main()

In unit testing section there is another exercise example. Will do this later for sure.

Python Date and time Function:

from datetime import time

a=time()
print("a=",a)

b=time(11,24,56)
print("b=",b)

c=time(hour=11, minute=34, second=56)
print("c=",c)

d=time(11,34,56,234566)
print(d)
from datetime import time

a=time(11,34,56,7)
print("hour=",a.hour)
print("minute=",a.minute)
print("second=",a.second)
print("microsecond=",a.microsecond)
from datetime import date

today=date.today()
print("Current year: ",today.year)
print("Current month: ",today.month)
print("Current day: ",today.day)

with strptime function:

from datetime import datetime
date_string="21 June, 2018"
print("Date string", date_string)

date_object=datetime.strptime(date_string,"%d %B, %Y")
print("date_object= ",date_object)

Date and Time from Different Timezones

from datetime import datetime
import pytz

local=datetime.now()
print("Local Time:",local.strftime("%m/%d/%Y, %H:%M:%S"))

tz_NY=pytz.timezone('America/New_York')
datetime_NY=datetime.now(tz_NY)
print("NY Time:",datetime_NY.strftime("%m/%d/%Y,%H:%M:%S"))

tz_Bangladesh=pytz.timezone('Asia/Dhaka')
datetime_Bangladesh=datetime.now(tz_Bangladesh)
print("Bangladesh Time:",datetime_Bangladesh.strftime("%m/%d/%Y, %H:%M:%S"))

Sleep Function:

import time
print("This is printed immediately")
time.sleep(2.4)
print("This is printedafter 2.4 seconds")

another updated version:

import time
while True:
    localtime=time.localtime()
    result=time.strftime("%I:%M:%S %p", localtime)
    print(result, end="", flush=True)
    print("\r", end="", flush=True)
    time.sleep(1) #1 second

To know much about it: Programiz.com is good

Sleeping and Threading: Those process is also good to go

import threading
import time
def print_hello():
    for i in range(4):
        time.sleep(0.5)
        print("hello")

def print_hi():
    for i in range(4):
        time.sleep(0.7)
        print("Hi")

t1=threading.Thread(target=print_hello)
t2=threading.Thread(target=print_hi)

t1.start()
t2.start()

 

Scripting With Python:

Image Processing With Python: Here we are using python Pillow library for that.

Code for sharpen and blur:

from PIL import Image, ImageFilter

img=Image.open('.\images\coffee.jpg')
filtered_img=img.filter(ImageFilter.SHARPEN)
filtered_img.save("sharpen.png", 'png') #png because it supports image filters
# print(img.format)
# print(img.size)
# print(img.mode)r
# print(dir(img))

convert:

from PIL import Image, ImageFilter

img=Image.open('.\images\coffee.jpg')
filtered_img=img.convert('L')

filtered_img.save("blackwhite.png", 'png') #png because it supports image filters

 

JPEG to PNG Converter from File Directory(Project):

import sys
import os
from PIL import Image

#grab first and second argument
image_folder=input("Image folder name:")
output_folder=input("Output folder name:")

#sys.argv[1]
#sys.argv[2]

print(image_folder,output_folder)

# n = input("File Name Please:")
# print("Folder to convert to PNG:", n)
# print("\nName of directory:", sys.argv[0])
##check is new/exists, if not then create
#print(os.path.exists(output_folder))
if not os.path.exists(output_folder):
    os.makedirs(output_folder)
##loop through Pokedex
for filename in os.listdir(image_folder):
    img = Image.open(f'{image_folder}{filename}')
    clean_name=os.path.splitext(filename)[0]
#    print(clean_name)
    img.save(f'{output_folder}{clean_name}.png', 'png')
    print('All done!')
##convert images to png



##save to the new folder

Python PDF file create script:

pip3 install PyPDF2
import PyPDF2

#opening the dummy.pdf file
with open('dummy.pdf','rb') as file: #rb is to read binary
    reader=PyPDF2.PdfFileReader(file)
    page=reader.getPage(0)
    print(page.rotateCounterClockwise(90))

#writing the rotated file to tilt.pdf
    writer = PyPDF2.PdfFileWriter()
    writer.addPage(page)
    with open('tilt.pdf', 'wb') as new_file: #wb is to write binary
        writer.write(new_file)

Pycharm and sys.argv related problem solution: This youtube video has cleared that for me. So I think it is possible to work with that in the windows based terminal

 

PDF maker with python:

import PyPDF2
import sys

inputs = sys.argv[1:]


def pdf_combine_func(pdf_list):
    merger = PyPDF2.PdfFileMerger()
    for pdf_name in pdf_list:
        print(pdf_name)
        merger.setPageLayout(layout='/TwoColumnRight')
        merger.append(pdf_name, bookmark='twopage.pdf')
    merger.write('super.pdf')


pdf_combine_func(inputs)

PDF maker with Watermark:
Unfortunately after several tries I could not make the created pdf file with watermark open. Maybe some technical errors are inside.
Sharing here thre code:

import PyPDF2

template = PyPDF2.PdfFileReader(open('super.pdf', 'rb'))
watermark = PyPDF2.PdfFileReader(open('wtr.pdf', 'rb'))
output = PyPDF2.PdfFileWriter()

for i in range(template.getNumPages()):
    page = template.getPage(i)
    page.mergePage(watermark.getPage(0))
    output.addPage(page)

    with open('watermarked_output.pdf', 'wb') as file:
        output.write(file)

Programming with python for sending email:

import smtplib

from email.message import EmailMessage
from string import Template
from pathlib import Path

#email object created from EmailMessage class
html=Template(Path('index.html').read_text())
email=EmailMessage()
email['from'] = 'Zaki Live'
email['to'] = ''
email['subject'] = 'How are u ??'

#email.set_content('I am learning python')
#email.set_content(html.substitute(name='TinTin'))

email.set_content(html.substitute({'name': 'TinTin'}), 'html')
with smtplib.SMTP(host='smtp.gmail.com', port=587) as smtp:
    smtp.ehlo()
    smtp.starttls()
    smtp.login('', '')
    smtp.send_message(email)
    print('All good boss!!!!')

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
 You are now happy $name
</body>
</html>

Password checker creation:

import requests
import hashlib

#k_anonymity we use here first 4 word
#response200 is good

def request_api_data(query_char):
    url = 'https://api.pwnedpasswords.com/range/' + query_char
    response = requests.get(url)
    print(response.status_code)
    if response.status_code != 200:
        print(f'Everything is not good! {response.status_code}')
        raise RuntimeError(f'Error fetching: {response.status_code}, check the api and try again')
    return response

def read_res(response):
     print(response.text)
# def get_password_leaks_count(hashes, hash_to_check):


def pwned_api_check(password):
    sha1password = hashlib.sha1(password.encode('utf-8')).hexdigest().upper()
    first5_char, tail = sha1password[:5], sha1password[5:]
    response = request_api_data(first5_char)
    print(response)
    return read_res(response)

    #request_api_data('123')
    pwned_api_check('123')

Udemy Python Course Zero to Mastery Blog Post Part 2

It would be a great help, if you support by sharing :)
Author: zakilive

Leave a Reply

Your email address will not be published. Required fields are marked *