21csc203p-App - Unit 4
21csc203p-App - Unit 4
Example:
• It does not support iteration like loop statements and conditional statements like If-Else
• Functional programming languages are designed on the concept of mathematical functions that use conditional expressions
and recursion to perform computation.
Example:
def inc(x): Note : Function involving Reading files,
return x+1 using global data, random numbers are impure functions
list=[8,3,7,5,2,6]
x=map(inc,list) #print(list)
print(x)
Note: if a function relies on the global variable or class member’s data, then it is not pure. And in such cases, the return value of that
function is not entirely dependent on the list of arguments received as input and can also have side effects.
• The above code performs recursion task as the loop by calling itself with a new start and a new accumulator.
• In imperative programming, this means “take the current value of x, add 1 and put the result back into x.” In functional
programming, however, x = x + 1 is illegal. That’s because there are technically no variables in functional programming.
• Using immutable data structures, you can make single or multi-valued changes by copying the variables and calculating new
values,
• Since FP doesn’t depend on shared states, all data in functional code must be immutable, or incapable of changing
• Higher-order functions are functions that take at least one first-class function as a parameter
• Examples:
• name_lengths = map(len, ["Bob", "Rob", "Bobby"])
• Higher Order functions are map, reduce, filter
Functional style of getting a sum of a list: # or the pure functional way in python using higher order
new_lst = [1, 2, 3, 4] function
def sum_list(lst):
if len(lst) == 1: import functools
return lst[0] print(functools.reduce(lambda x, y: x + y, new_lst))
else:
return lst[0] + sum_list(lst[1:])
print(sum_list(new_lst))
import random
names = ['Seth', 'Ann', 'Morganna']
team_names = map(lambda x: random.choice(['A Team','B Team']),names)
print names
Example:
sum = reduce(lambda a, x: a + x, [0, 1, 2, 3, 4])
print sum // 10
Example:
def f(x):
return x%2 != 0 and x%3 ==0
filter(f, range(2,25))
• Allows Functions having variables that have not yet been computed
In Python, the logical expression operators and, or, and if-then-else are all non-strict. We sometimes call them short-circuit
operators because they don't need to evaluate all arguments to determine the resulting value.
The following command snippet shows the and operator's non-strict feature:
Syntax:
lambda argument(s): expression
Example:
remainder = lambda num: num % 2 [(lambda x: x*x)(x) for x in [2,6,9,3,6,4,8]]
print(remainder(5))
UNIT IV : Pythonic Programming 15
Functional Programming – Closure
Basically, the method of binding data to a function without actually passing them as parameters is called closure. It is a function
object that remembers values in enclosing scopes even if they are not present in memory.
Example:.
def counter(start=0, step=1):
x = [start]
def _inc():
x[0] += step
return x[0]
return _inc
c1 = counter()
c2 = counter(100, -10)
c1()
//1
c2()
90
UNIT IV : Pythonic Programming 16
Pure Functions in Python
• If a function uses an object from a higher scope or random numbers, communicates with files and so on, it might be impure
List Comprehensions
• A popular Python feature that appears prominently in Functional Programming Languages is list comprehensions. Like the map
and filter functions, list comprehensions allow us to modify data in a concise, expressive way.
# Output: 10
Note: you want to pass a function as an argument to higher-order functions, that is, functions that take other functions as their
arguments. UNIT IV : Pythonic Programming 19
map() Function
Example with Map
Example Map with lambda
from math import sqrt
tup= (5, 7, 22, 97, 54, 62, 77, 23, 73, 61)
newtuple = tuple(map(lambda x: x+3 , map(sqrt, [1, 4, 9, 16])
Syntax:
map(function, iterables)
Syntax:
filter(func, iterable)
The following points are to be noted regarding filter():
• Unlike map(), only one iterable is required.
• The func argument is required to return a boolean type. If it doesn't, filter simply returns the iterable passed to it. Also, as only
one iterable is required, it's implicit that func must only take one argument.
• filter passes each element in the iterable through func and returns only the ones that evaluate to true. I mean, it's right there in
the name -- a "filter".
Example:
def isOdd(x): return x % 2 == 1
filter(isOdd, [1, 2, 3, 4])
s = functools.reduce(lambda x,y:x+y,even)
def s_total(a,b,c):
return a*b+c#a=5,b=15, c=from list s
= functools.partial(s_total,5,15)
l= [13,54,76,89,10]
for i in l:
print(s(i))
1 Treats computation as the evaluation of mathematical Derived from structured programming, based on the
functions avoiding state and mutable data concept of modular programming or the procedure call
2 Main traits are Lambda Main traits are Local variables, sequence,
alculus, compositionality, formula, recursion, referential selection, iteration, and modularization
transparency
3 Functional programming focuses on expressions Procedural programming focuses on statements
4 Often recursive. Always returns the same output for a The output of a routine does not always have a direct
given input. correlation with the input.
Everything is done in a specific order.
5 Order of evaluation is usually undefined.
3 What it focuses is on: "What you are doing. in the What it focuses is on "How you are doing your
programme." programming."
4 Supports Parallel Programming. No supports for Parallel Programming.
5 Its functions have no-side effects. Method can produce many side effects.
6
Flow Control is performed using function calls & function Flow control process is conducted using loops and
calls with recursion. conditional statements.
7
Execution order of statements is not very important. Execution order of statements is important.
8 Supports both "Abstraction over Data" and "Abstraction
Supports only "Abstraction over Data".
over Behavior."
Syntax:
this is the rules about how to form formulas; this is usually the easy part of a logic.
Semantics:
About the meaning carried by the formulas, mainly in terms of logical consequences.
Inference rules:
Inference rules describe correct ways to derive conclusions
Predicates :
Define relations between their arguments. Logically, a Logic program states what holds. Each predicate has a name, and zero or more
arguments. The predicate name is a atom. Each argument is an arbitrary Logic term. A predicate is defined by a collection of clauses.
Clause :
A clause is either a rule or a fact. The clauses that constitute a predicate denote logical alternatives: If any clause is true, then the whole
predicate is true.
+big('bear')
+big('elephant')
+small('cat')
+brown('bear')
+black('cat')
+grey('elephant')
Consider the 3 fact saying ‘cat’ is a smallest animal and fact 6 saying the elephant is grey in color
dark(X)<=black(X)
dark(X)<=brown(X)
Consider rule 1 saying the animal color is black its consider to be dark color animal
print(pyDatalog.ask('father_of(X,jess)'))
Output:
{('jack',)}
X
print(father_of(X,'jess'))
Output:
jack
X
Fact
X +male('adam')
Predicat Clause
e
son(X,Y)<= male(X) & parent(Y,X)
Query
print(pyDatalog.ask('son(adam,Y)'))
+male('adam')
+female('anne')
+female('barney')
+male('james')
+parent('barney','adam')
+parent('james','anne')
#The first rule is read as follows: for all X and Y, X is the son of Y if there exists X and Y such that Y is the parent of X and X is male.
#The second rule is read as follows: for all X and Y, X is the daughter of Y if there exists X and Y such that Y is the parent of X and X is
female.
son(X,Y)<= male(X) & parent(Y,X)
daughter(X,Y)<= parent(Y,X) & female(X)
print(pyDatalog.ask('son(adam,Y)'))
print(pyDatalog.ask('daughter(anne,Y)'))
print(son('adam',X))
UNIT IV : Pythonic Programming 39
Logical Programming Paradigm
pyDatalog.create_terms('factorial, N')
factorial[N] = N*factorial[N-1]
factorial[1] = 1
print(factorial[3]==N)
+works_in('Mary', 'Production')
+works_in('Sam', 'Marketing')
+works_in('John', 'Production')
+works_in('John', 'Marketing')
+(manager['Mary'] == 'John')
+(manager['Sam'] == 'Mary')
+(manager['Tom'] == 'Mary')
Soln
from pyDatalog import pyDatalog
pyDatalog.create_terms('X,Y,Z,professor,lecturer, dean')
+professor('lucy')
+professor('danny')
+lecturer('james')
dean(X)<=professor(X)
print(dean(X))
rules
friends(X,Y) :- likes(X,Y),likes(Y,X). /* X and Y are friends if they like each other */
hates(X,Y) :- not(likes(X,Y)). /* X hates Y if X does not like Y. */
enemies(X,Y) :- not(likes(X,Y)),not(likes(Y,X)). /* X and Y are enemies if they don't like each other */
• A system is said to be parallel if it can support two or more actions executing simultaneously i.e., multiple actions are
simultaneously executed in parallel systems.
• The evolution of parallel processing, even if slow, gave rise to a considerable variety of programming paradigms.
• Parallelism Types:
• Explicit Parallelism Message Passing Architecture
• Implicit Parallelism
Pipeline
• In pipeline paradigm, a number of processes form a virtual
pipeline.
• A continuous data stream is fed into the pipeline, and the
processes execute at different pipeline stages simultaneously in an
overlapped fashion.
Example:
import threading
from threading import *
jobs = []
for i in range(1,5):
p = multiprocessing.Process(target=worker, args=(i+10,))
jobs.append(p)
p.start()
Objects shared by multiple tasks have to be safe for concurrent access. Such objects are called protected. Tasks accessing such an
object interact with each other indirectly through the object.
An access to the protected object can be:
• Lock-free, when the task accessing the object is not blocked for a considerable time;
• Blocking, otherwise.
Blocking objects can be used for task synchronization. To the examples of such objects belong:
• Events;
• Mutexes and semaphores;
• Waitable timers;
• Queues
UNIT IV : Pythonic Programming 61
Issues Concurrent Programming Paradigm
def decr():
global x
for i in range(COUNT):
x -= 1
print(x)
R-Locks:
R-Lock class is a version of simple locking that only blocks if the lock is held by another thread. While simple locks will block if
the same thread attempts to acquire the same lock twice, a re-entrant lock only blocks if another thread currently holds the lock.
Semaphore:
A semaphore has an internal counter rather than a lock flag, and it only blocks if more than a given number of threads have
attempted to hold the semaphore. Depending on how the semaphore is initialized, this allows multiple threads to access the same
code section simultaneously.
def adder(f,count):
while count > 0:
f.incr()
count -= 1
UNIT IV : Pythonic Programming 67
Synchronization in Python using Semaphore
import threading
import time def consumer():
print "I'm a consumer and I wait for data."
done = threading.Semaphore(0) print "Consumer is waiting."
item = None done.acquire()
print "Consumer got", item
def producer():
global item t1 = threading.Thread(target=producer)
print "I'm the producer and I produce data." t2 = threading.Thread(target=consumer)
print "Producer is going to sleep." t1.start()
time.sleep(10) t2.start()
item = "Hello"
print "Producer is alive. Signaling the consumer."
done.release()
In the context of the Internet, clients are typically run on desktop or laptop computers attached to the Internet looking for
information, whereas servers are typically run on larger computers with certain types of information available for the clients to
retrieve. The Web itself is made up of a bunch of computers that act as Web servers; they have vast amounts of HTML pages and
related data available for people to retrieve and browse. Web clients are used by those of us who connect to the Web servers and
browse through the Web pages.
Network programming uses a particular type of network communication known as sockets. A socket is a software abstraction for an
input or output medium of communication.
Stream Socket:
• A stream socket, or connected socket, is a socket through which data can be transmitted continuously. A stream socket is more
akin to a live network, in which the communication link is continuously active. A stream socket is a "connected" socket through
which data is transferred continuously.
listen(backlog) : This method listens for the connection made to the socket. The backlog is the maximum number of queued
connections that must be listened before rejecting the connection.
accept( ) : This method is used to accept a connection. The socket must be bound to an address and listening for connections. The
return value is a pair(conn, address) where conn is a new socket object which can be used to send and receive data on that
connection, and address is the address bound to the socket on the other end of the connection.