Monday 30 December 2019

decorator chaining


def supper(f):
    def inner():
        #b=f()
        return f().upper()
    return inner
#@supper
def display():
    return "hello"
result=supper(display)
print(result())
print(display())
"""output:
HELLO
hello
"""
Whenever we would like to apply the decorator function to the existing function, it is mandatory to send existing function as a parameter to the decorator function.
Ex:
def décor (fun):
  …
def normal():
  …
result=décor(normal)

To apply the decorator function automatically to any normal function, use @ symbol followed by decorator name above the function definition.
@supper
def display():
    return "hello"
so no need to call the decorator function explicitly sending normal function as a paratmeter.

Decorator chaining: A python program to apply two decorators to the same function using @ symbol
#a decorator that increments the value of a function by 2
def decor1(fun):
    def inner():
        a=fun()
        return a*2
    return inner
#a decorator that doubles the value of a function
def decor2(fun):
    def inner():
        a=fun()
        return a+2
    return inner
#take a function to which decorator should be applied
@decor1
@decor2
def count():
    return 4
""
@decor1
@decor2 this is equalant to
#result=decor1(decor2(count))
#print(result())
"""
"""output:
12
"""
Note: décor, inner are user defined words, instead we can give any name convention.

Related Video: https://youtu.be/Vm4BnLWTK4E
https://youtu.be/dqVMIgkZRiQ
Next:
Prev: Decorators

Using Lambda with filter () ,map() and reduce() function


Using lambdas with filter()
#without using lambda function with filter()
def even(n):
    if n%2==0:
        return True
    else:
        return False
a=[0,5,10,20,25,30]#created list
#b=list(filter(even,a))
b=list((even,a))
print(b)
"""output:
[0, 10, 20, 30]

filter() is used to filter the data from the given sequence based on some condition

Syntax: filter(function,sequence)

# Same program with using lambda function with filter()
"""def even(n):
    if n%2==0:
        return True
    else:
        return False"""

a=[0,5,10,20,25,30]#created list
b=list(filter(lambda n:n%2==0,a))
print(b)
#odd nos
b=list(filter(lambda n:n%2!=0,a))
print(b)
"""output:
[0, 10, 20, 30]
[5, 25]
"""
It is normally used with Lambda functions to separate list, tuple, or sets.
map() function

It is similar to filter() but it acts on each element of the sequence and generate new sequence.

Without lambda function:
a=[1,2,3,4,5]#list created
def double(n):
    return 2*n
b=list(map(double,a))
print(b)
"""output:
[2, 4, 6, 8, 10]
"""
#without lambda function
a=[1,2,3,4,5]#list created
"""def double(n):
    return 2*n
b=list(map(square,a))"""
b=list(map(lambda n:2*n,a))
print(b)
"""output:
[2, 4, 6, 8, 10]
"""
reduce() function

from functools import*
a=[10,20,30,40,50]
b=reduce(lambda x,y:x+y,a)
print(b)

"""
output:150
1q) if we don't write import:
Ans:NameError: name 'reduce' is not defined
Or we can write
from functools import*

"""
Reduce() function reduces sequence of elements into a single value by processing the elements according to the functionality.

Syntax: reduce(function,sequence)

Example:
from functools import*
a=[1,2,3,4,5]
b=reduce(lambda x,y:x*y,a)
print(b)
or
import functools
a=[1,2,3,4,5]
b=functools.reduce(lambda x,y:x*y,a)
print(b)
"""

output:120

Related video links:
https://youtu.be/tlexI5d6LI0
https://youtu.be/WgSk2cGcraQ


Next: Decorator function
Prev:Lambda function

Decorator function


def security(name):
    print("Thanks,",name,"Welcome")
#This function can allow all the persons including non-emp
security("Ravi")
"""output:
Thanks, Ravi Welcome
Thanks, Sita Welcome
"""
The above function displays the same msg for all the parameters i.e names. 
 But I want to modify this function to provide different msg for a different name without modifying the original function security() if outsiders enter. If the name is Sita, we can allow, other than Sita , we should not allow.
 
 By using Decorator function:
def decor(func):
    def inner(name):
        if name!='Sita':
            print("Sorry",name,"Please take the pass")
        else:
            func(name)
    return inner
def security(name):
    print("Thanks,",name,"Welcome")
"""output:
>>> modified=decor(security)
>>> modified("ravi")
Sorry ravi Please take the pass
>>> modified('Sita')
Thanks, Sita Welcome
>>> """
           
@Apply décor to the function
def decor(func):
    def inner(name):
        if name!='Sita':
            print("Sorry",name,"Please take the pass")
        else:
            func(name)
    return inner
@decor Apply décor to the below function
def security(name):
    print("Thanks,",name,"Welcome")
"""output:
>>> security("ravi")
Sorry ravi Please take the pass
>>> security("sita")
Sorry sita Please take the pass
>>> security("Sita")
Thanks, Sita Welcome
>>> """
In the above function when we call security() automatically décor() will be executed.
           
Note: décor is not a keyword, it is user-defined word, so instead of décor we can use any name, but while using user-defined word, same word should be used @userdefined

Example:
def modify(func):
    def inner(name):
        if name!='Sita':
            print("Sorry",name,"Please take the pass")
        else:
            func(name)
    return inner
@modify
def security(name):
    print("Thanks,",name,"Welcome")               


Decorator is a function which can take a function as argument and extend its functionality of existing function and returns modified function with extended functionality without modifies the original function.

Steps to use décor function:
1.     Define décor function with existing function name as a formal parameter      Example:                                                                                                                   def décor(fun):       
2.     Define a extend function inside the decorator function, this function decorates the extended functionality of existing function, passed to the decorator function.
Ex: def décor:
             Def inner():
                 ..logic to be extended
3.     Return the inner function or decorated functionality

def div(a,b):
    c=a/b
    return c
"""output:
>>> div(4,0) #leads to run time error
2.0
Here 4 is numerator, 0 is denominator
>>> div(2,4)
0.5
here 2 is numberator, 4 is denominator
>>>

 By using Decorator function:
def div(a,b):
    print(a/b)
#decorator function
def makeup(fun):#this is a decorator function
    def inner(a,b):#this is the inner function that modifies
        if b==0:
            print("Can not be divided")
        else:
            return fun(a,b)
    return inner
result=makeup(div)
result(4,0)
"""output:
Can not be divided"""
Here 4 is numerator, 0 is denominator
By using Decorator function


Related Video link: https://youtu.be/d-qTxNTiZPM
Next: decorator chaining
Prev Using Lambda with filter () function

Tower Of Hanoi


Tower of Hanoi
def toh(n,p1,p2,p3): #n= no of disks, p1=source pole,p2=intermediate, pole,                                     #p3=target pole
    if n>0: # at least one disk is required
        toh(n-1,p1,p3,p2) #move pole1 to pole 2, p3 is acting as intermediate pole
        print("move a disk from pole %i pole %i"%(p1,p3))
        toh(n-1,p2,p1,p3) #move n-1 disk from pole 2 to pole 3,pole1 acting as                #intermediate pole
n=int(input("enter no of disks "))
toh(n,1,2,3)# function call
       
"""output:
>>> toh(2,1,2,3)
enter no of disks 2
move a disk from pole 1 pole 2
move a disk from pole 1 pole 3
move a disk from pole 2 pole 3
>>>
>>> """ 

Related video link: https://youtu.be/Pkhmy6eFM0Y
Prev Recursive Function
Next:Lambda function

lists methods



pop():
It is a predefined function, which is used to delete the values from the list.  It returns the deleted value.
Use index number to delete particular element.
If you are not using the index value, last element is deleted.
#pop()
a=[2,3,6,20] #list is created with elements
print(a)
c=a.pop()#it deletes the last element, and returns
print(c)
"""
output:
[2,3,6,20]
20
"""
Removing a particular item from the nested list : using remove()
a=[[10,20,30],[40,50,60]]
print(a)
print(a[1][0])#40
#a[1].remove(50) #[[10,20,30],[40,50,60]]
print("after removing")
print(a)


"""
output:
[[10, 20, 30], [40, 50, 60]]
"""
Removing a particular element from the nested list using del operator
a=[[10,20,30],[40,50,60]]
print(a)
print(a[1][0])#40
del a[1][2]#[[10, 20, 30], [40, 50]]
print("after removing")
print(a)

"""
output:
[[10, 20, 30], [40, 50]]
"""

#find the smallest and largest value in the list
a=[10,20,78,90,4,30] #list is created
print(a)
print(min(a))# 4
print(max(a))#90

index():
it is a predefined function, it used to find the index value of the particular element.
# search the particular element in the list and find the element
a=[10,20,78,90,4,30] #list is created
print(a)
print(a.index(90))

Comparing the two lists:
a,b=[10,20,30,40],[10,20,30,40] #two lists are created
#a=[10,20,30,40]
#b=[10,20,30,40]
print(id(a))
print(id(b))
print(a==b) #comparing the two lists
"""
output:
58443336
58443016
True
"""

Example2:
a,b=[10,20,30,40],[30,20,10,40] #two lists are created
#a=[10,20,30,40]
#b=[10,20,30,40]
print(id(a))
print(id(b))
print(a==b) #comparing the two lists
"""
output:
55952848
55952528
False
"""

By using the comparator operator, it compared the two content of the objects with ordered list

Comparing the two lists with the help of sort() function:
a,b=[10,20,30,40],[30,20,10,40] #two lists are created
#a=[10,20,30,40]
#b=[10,20,30,40]
print(id(a))
print(id(b))
print(a.sort()==b.sort())
"""
output:
49923496
49923176
True
"""

#write a program no of times 'n' appears in the list
a=["rama","sitha","ravi","venu","ravi"]
print(a.count("ravi"))

"""
2
"""


#write a program, sort the values in reverse and non-reverse values
a=[10,30,60,80,5,20]
print("Before sorting")
print(a)
#a.reverse()
#print(a)
print("after sorting, where reverse=True")
a.sort(key=None,reverse=True)
print("after sorting, where reverse=False")
a.sort(key=None,reverse=False)
print(a)
"""
output:
Before sorting
[10, 30, 60, 80, 5, 20]
after sorting, where reverse=True
[80, 60, 30, 20, 10, 5]
"""
#by using the negative index nos we can reverse the list:
#write a program, sort the values in reverse and non-reverse values
a=[10,30,60,80,5,20]
print("Before sorting")
print(a)
print("after performing reverse order")
print(a[::-1])

"""

Before sorting
[10, 30, 60, 80, 5, 20]
after performing
[20, 5, 80, 60, 30, 10]
"""
Related video: https://youtu.be/J56YFtcSykQ

 Next topic: Tuple

Wednesday 4 December 2019

return statement


Return statement:
#example program for return statement
def add(a,b):
    return(a+b)
d=add(5,4)#function call, return value is stored in d
print(d)

function can take input values as parameters and executes logic, and returns output to the function call with return statement.

#example program for return statement
def prime(n):
    ctr=0
    for i in range(1,n+1):
        if n%i==0:
            ctr+=1
    if ctr==2:
        print(n,"is prime")
    else:
        print(n,"is not prime")
"""output:
>>> prime(3)
3 is prime
>>> prime(4)
4 is not prime
>>> prime(6)
6 is not prime
>>> 
""""
 Assignment function that generates prime numbers:
10
2,3,5,7,11,13,17,19,23,29

Related video: https://youtu.be/EpizFbmfC5s

Prev   Calling a function
Next: A function return more than one value
Related videos: https://youtu.be/SIwAaHwKctY

Tuesday 3 December 2019

Introduction to *args and **kwargs in Python

1.     Variable length arguments
we define a function to make a reusable code that performs specific operation. To execute that operation, we call a function with the specific value, this value is called a function argument in Python.
def add(a,b):
    c=a+b
    print(c)
#function call
add(2,3)# valid
add(2)#invalid
add(2,4,5)#invalid

Introduction to *args and **kwargs in Python

In Python, we can pass a variable number of arguments to a function using special symbols. There are two special symbols:
We use *args and **kwargs as an argument when we are unsure about the number of arguments to pass in the functions.
1.     *args (Non Keyword Arguments)
2.     **kwargs (Keyword Arguments)
def add(*args):
    sum=0
    for i in args:
        sum=sum+i
    print(sum)
#function call
add(2,3)# valid
add(2)#valid
add(2,4,5)#valid
# *args for variable number of arguments
def f1(*argv):
            for i in argv:
                        print (i)
f1('Hello', 'Ram')
"""
output:
Hello
Ram
1.     Can we give def f1(*n): ?
Ans: we will get error
>>> """
#Variable length arguments
def add(*n):
    sum=0
    for i in n:
        sum=sum+i
    print("total=",sum)
add()
add(10)
add(10,6)
add(2,3,4)
"""
output:
total= 0
total= 10
total= 16
total= 9
>>>
"""
Sometimes we can pass variable number of arguments to our function, such type of arguments are called variable length arguments. We can declare a variable length argument with * symbol
We can call this function by passing any number of arguments including zero number. Internally all these values represented in the form of tuple.

A tuple is a collection of elements/items of different data types is called tuple.
A tuple is similar to list. Elements are separated by comma operator and enclosed within parentheses ().

Difference between list and tuple is: List elements can be modified as it is mutable. Whereas tuple elements can not be modified as it is immutable. So tuple is treated as a read-only list.

Example:
t=(10,-20,10,2.4,”raj”,”$”,True)

Ex2: We can mix variable length arguments with positional arguments
#Variable length arguments
def add(a,*n):
    print(a)
    sum=0
    for i in n:
        sum=sum+i
    print("total=",sum)
#add()Error
add(10)
add(10,6)
add(2,3,4)
"""
output:
10
total= 0
10
total= 6
2
total= 7
>>>
"""
Note: After variable length argument, if we are taking any other arguments then we should provide values as keyword argument.
#Example program on variable length arguments
def f1(*n,a):
    for i in n:
        print(i)
    print("a=",a)
f1('sita','ram',5)
"""output:
Note1: f1('sita','ram',a=5)
sita
ram
a= 5

(2)f1('sita','ram',5) #Error bcoz after variable length argument, if we are taking any
other arguments then we should provide values as keyword arguments
>>>
"""

def f1(a, b, c):
            print("a:", a)
            print("b:", b)
            print("c:", c)
           
# Now we can use *args or **kwargs to
# pass arguments to this function :
args = ("Hyd", "Vij", "Kadapa")
f1(*args)

#kwargs = {"a" : "Hyd", "b" : "Vij", "c" : "Kadapa"}
#f1(**kwargs)
"""output:
a: Hyd
b: Vij
c: Kadapa
>>> """


Related Videohttps://www.youtube.com/playlist?list=PL2mD2CO8TKlJdFbbtuhTXPQk2tNQx0pb1

Previous: Formal and actual parameters
Next: kwargs(keyword arguments)

Files with Exception handling

#Ask the user to take two input integer values var a,b try:     a=int(input("enter any integer value:"))     b=int(input(&qu...