UNIT-4 (functional and OOPS) Flashcards
Functional Programming
programs made using function
uses pure functions, recursive functions, nested functions ,lambda functions etc.
treats functions as values and pass them to functions as parameters
more readable and easily understandable.
function signature => information about them i.e.their arguments and return type etc
HIGHER ORDER FUNCTIONs
* functions that take functions as arguments, also return functions. (Ex: Callback Functions)
* understood very easily
* Testing and debugging is easier. use immutable values
* better modularity with a shorter code
- lazy evaluation avoids repeated evaluation because the valueis evaluated and stored only when it is needed.
- Example: Lazy Map & Lists ,tuples, sets etc
lamda
functions without the name.
=> anonymous/throw away functions.
=> number of arguments but only one expression.
=>(Implicit return)
=>used when you need a particular function for a short period of time.
ADV:
useful in defining the in-line functions.
Most suitable when it is used as a part of another function(especially with map, filter and reduce functions)
Less Code (Concise code)
Syntax: lambda input arguments: expression / Output
Input arguments: can have multiple arguments by use of commas
* Expression or output: Expression gets evaluated and results are returned
EXAMPLE:
square=lambda n : n*n
print(square(4)) #Function Call
ANOTHER EXAMPLE maximum=lambda a,b : a if a>b else b
We can use the same function definition to make two functions
def myfunc(n):
return lambda a : a * n
double_N = myfunc(2)
triple_N = myfunc(3)
print(double_N(15))
print(triple_N(15))
Output
30,45
Map()
applies a function to each element of an iterable (like a list or a tuple) and returns a new iterable object.
Syntax: map(function, iterables)
- causes iteration through iterable
is lazy
can force an iteration of the map object by passing the map object as an argument for the list or set constructor.
- We can pass one or more iterable to the map() function.
LAZY EVALUTION
Lazy and Eager objects:
object is created when it is needed whereas eager an object is created as soon it is instantiated.
As map object can be iterated one item in eachloop. for list, all the values at one time.
optimizing code and improving performance
used to delay or avoid computations, save memory by avoiding intermediate results,
explore multiple possibilities without committing to one.
* eager evaluation is preferable when you want to perform computations as soon as possible
EXAMPLE CODE
num = (1, 2, 3, 4)
result = map(lambda x: x + x, num)
print(list(result))
Output:
<class ‘map’>
[2, 4, 6, 8]
ANOTHER EXAMPLE
num = [1, 2, 3, 4, 5]
def double_num(n):
if n% 2 == 0:
return n * 2
else:
return n
result = list(map(double_num,num)
print(result)
Output: The modified list is [1, 4, 3, 8, 5]
stFilter()
filters sequence with function that tests each element in the sequence to be true or not.
filter(function,sequence/iterable)
*sequence: which needs to be filtered, it can be sets, lists, tuples, or containers of any iterators.
*Returns: an iterator that is already filtered.
CHARACTERISTICSInput : an iterable of some number of elements
- Output: a lazy iterable
- Elements in the output: apply the callback on each element of the iterable – if the function returns true, then the input element is
selected else input element is rejected.
EXAMPLE
list the marks greater than 70
marks = [55, 78, 90, 87, 65, 45]
def myFunc(m):
if m <70 :
return False
else:
return True
Distinction = list(filter(myFunc, marks))
print(“Students with marks greater than 70 are”,Distinction)
Output:
Students with marks greater than 70 are [78, 90, 87]
reduce
Syntax
applies a given function to the elements of an iterable ,reducing them to a single value
defined in “functools” module.
=>function argument is a function that takes two arguments and returns a single value.
=>first argument is the accumulated value, and the second argument is the current value from the iterable.
=>iterable argument is the sequence of values to be reduced.
=> initializer argument is => initial value. else, first element of the iterable is used as the initial value.
Working of reduce function:
first two elements of the sequence are picked and the result is obtained.
same function is applied to the previous result and the number after 2nd element and result is again stored
will be n – 1 calls if no initializer is specified.
final result is returned as a single value.
EXAMPLE
from functools import reduc
numbers = [1, 2, 3, 4]
def add(a, c)
return a + c
result = reduce(add, numbers)
functools.reduce(function, iterable,[initializer])
print(result)
Zip()
function zip => two or more iterables into a single lazy iterable of tuples.
* It does not have any callback function.
used to map the similar index of multiple containers so that they can be used just using a single entity
Elements from corresponding positions are paired
together.
The resulting iterable contains tuples
EXAMPLE without ZIP
Consider the code below which pairs the two lists:
m=[1,2,3]
n=[4,5,6]
l_new=[]
for i in range(len(m)):
l_new.append((m[i],n[i]))
print(l_new)
less code using zip. We
can observe the same output.
Syntax : zip(*iterators)
print(list(zip(m,n)))
Output
[(1, 4), (2, 5), (3, 6)]
[(1, 4), (2, 5), (3, 6)]
zipped=[(1, 4), (2, 5), (3, 6)]
SYNTAX=zip(*zipped)
UNEQUAL SIZE
Example 5: Zipping list with unequal size.(Two ways)
lis1 = [1,2,3]
lis2 = [4,5,6,7]
print(list(zip(lis1,lis2)))
The same can be acheived
using the directory comprehension as:
result={k:v for k,v in zip(lis1,lis2)}
print(result)
Output
[(1, 4), (2, 5), (3, 6)]
{1: 4, 2: 5, 3: 6}
List comprehension
concise way of defining and creating a list
used to create functionality within a single line of code.
Return value is always a new list obtained by evaluating the expression in the context of for and if
*faster in processing than a list using for loop.
list = [expression for <var> in <iterable> [if condition]]</iterable></var>
m=[1,2,3]
n=[4,5,6]
print([x+y for x in m for y in n])
Output:
[5, 6, 7, 6, 7, 8, 7, 8, 9]
POP(Procedure Oriented Programming)
Programming Paradigm: Style to write solution
=> uses procedures.
* Procedure: instructions used to accomplish a specific task.
=> routines, sub-routines, functions etc
Object Oriented Programming (OOP)
Focus => data and the operations that manipulate the data.
code by representing real- entities as objects
to develop big and complex projects
FEATURES:
Data Abstraction:
* The way you view an object(Ex: apples)
* essential features without background details
Data encapsulation:
* Binding of data and procedures as a single unit.
* Encapsulation: a way to implement data abstraction.
Data Hiding:
* who can access the data .
=> using access specifiers.
Inheritance:
* one class (child) to derive the capabilities of another class(parent)
* Benefit: Code reusability
Polymorphism:
* object of a class to behave diff in response to the data.
KEY CONCEPTS
Class:
* method to create => entity.
* Blueprint/template for creating objects.
*a type and implementation.
* specifies set of instance vars/attributes(data each object of the class will store) and methods
(functions that define the behavior of the objects) that objects of that class has
Syntax OOP
Syntax: (To create a class)
class ClassName:
<statement-1> . <statement-N>
Example 1
class Car:
#first letter should be CAP
def\_\_init\_\_(self,make,color,year ):
#Special method that creates objects
self.make=make
self.color=color
self.year=year
def drive(self):
print(""+self.make+" go vroom")
#this is a method
#self => object that uses this method
TO CREATE OBJECT
Car1=Car("BMW","Blue", "2014" )
Car1.drive()
OUTPUT:
BMW
Blue
2014
BMW go vroom
</statement-N></statement-1>
OOPS Instances
instance => single object from a class. class = blueprint, and an instance => specific object built using that blueprint.
- Represents real entities
- Have their own attributes attributes and methods as defined by the class.
Objects have:
1.Identity: Each object = unique identity
2.Type: type() =>type of an object.
3.Value: Objects have a value that can be modified or accessed (like integers,
strings, lists)
EXAMPLE
class Car:
pass
c1 = Car()
print(c1)
print(type(c1))
print(id(c1))
Output:
<__main__.Car object at 0x000001C9E2200DC0>
<class ‘__main__.Car’>
1966593805760
Instantiation
Constructor
Instantiation
* existence of a class doesn’t create
* Object must be created explicitly
* To create an object => c1= Car() => object(c1) of class Car
* (.)Dot operator -> access attributes of the class.
Ex: c1.car_name
Constructor
* special func of the class called when object is created
* __init__ => name
*invoked automatically and implicitly when object is created.
* used to initialize the internal state of an object, and create instance vars
self => reference to the object used to access
attributes and methods and should be the first parameter
Destructor
* special func => __del__, performs cleanup => when an object is deleted.
* automatically called just before an object is removed by the garbage collector.
* often used to release resources before an object is removed
module garbage collector automatically manages memory and calls destructors when objects are not needed
Destructor: Called when the object is deleted
def __del__(self):
print(f”Person {self.name} is deleted.”)
Types Of constructors
Fixed actual value
Types of Constructors :
1. Non Parameterized constructor
class Person:
def __init__(self):
self.name = “Joe”
#Fixed actual value
self.age = 25
def display(self): print(f"Name: {self.name}, Age: {self.age}") person1 = Person() person1.display()
- Parameterized constructor
class Car:
def__init__(self,make,color,year ):
self.make=make
self.color=color
self.year=year
def drive(self):
print(““+self.make+” go vroom”)
Car1=Car(“BMW”,”Blue”, “2014” )
Car1.drive()
can add instance vars outside the class
p.transmission=‘M’
Getter and Setter Method:
Getter:
* Used to retrieve the value of attribute of a class without directly exposing it.
Setter:
*to modify attribute of a class.
*controlled modification of attribute’s value by performing checks or
validations before assigning new value
Getter syntax:
def get_attribute(self):
return self.__attribute
Setter Syntax
def set_attribute(self, value):
self.__attribute = value
predefined functions
1 setattr() sets the value of attribute of the
Syntax setattr(object, attribute, value)
2 getattr() returns the value of the specified attribute
Syntax: getattr(object, attribute, default)
3 hasattr() returns True if the specified object has specific attribute, else False.
Syntax hasattr(object, attribute)
4 delattr() will delete the specified attribute
Syntax delattr(object, attribute)
Getter and Setter code
class Person:
def __init__(self, name):
self.__name = name # Private attribute
# Getter for name def get_name(self): return self.\_\_name # Setter for name def set_name(self, name): self.\_\_name = name
Create an object of Person
person = Person(“Alice”)
Access name using getter
print(person.get_name()) # Output: Alice
Modify name using setter
person.set_name(“Bob”)
print(person.get_name()) # Output: Bob