Skip to content

Commit cd7d01e

Browse files
committed
Added first_class functions , closures and decorators and a logging_project to understand decorators
1 parent acc7386 commit cd7d01e

8 files changed

+204
-0
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#Logging Problem
2+
#Keeping track of how many times a function is run and what arguments were passed to it
3+
4+
5+
from functools import wraps
6+
7+
8+
9+
def my_logger(original_function):
10+
import logging
11+
logging.basicConfig(filename='{}.log'.format(original_function.__name__),level=logging.INFO)
12+
@wraps(original_function)
13+
def wrapper_function(*args,**kwargs):
14+
print('Ran with args : {} and kwargs : {}'.format(args,kwargs))
15+
logging.INFO('Ran with args : {} ,and kwargs : {}'.format(args,kwargs))
16+
return original_function(*args,**kwargs)
17+
return wrapper_function
18+
19+
20+
def my_timer(original_function):
21+
import time
22+
@wraps(original_function)
23+
def wrapper(*args,**kwargs):
24+
t1 = time.time()
25+
result = original_function(*args,**kwargs)
26+
t2 = time.time()
27+
run_time = t2-t1
28+
print('{} function ran in {} seconds'.format(original_function.__name__,run_time))
29+
return original_function
30+
return wrapper
31+
32+
33+
34+
35+
# @my_logger
36+
# def display_info(name,age):
37+
# print('display_info ran with arguments ({},{})'.format(name,age))
38+
39+
40+
import time
41+
42+
@my_logger
43+
@my_timer
44+
def display_info(name,age):
45+
time.sleep(1)#TO set delay so that we get some results otherwise it will run fast and give 0.00 sec
46+
print('display_info ran with arguments ({},{})'.format(name,age))
47+
48+
display_info('Vipulkumar',19)
49+
50+
#Change stack arrangement of the decorators and see the difference
51+
52+

src/closureFunc_2.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
def outer_function(msg):
3+
def inner_function():
4+
print(msg)
5+
6+
return inner_function #removed Paranthesis
7+
8+
9+
Hi_func = outer_function('Hi') #MY func is = inner_function(){ready to be executed}
10+
Bye_func = outer_function('Bye')
11+
Hi_func()
12+
Bye_func()

src/closureFunctions.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
def outer_function():
3+
message = 'Hi'
4+
5+
def inner_function():
6+
print(message)
7+
8+
return inner_function #removed Paranthesis
9+
10+
11+
my_func = outer_function() #MY func is = inner_function(){ready to be executed}
12+
my_func()
13+
my_func()
14+
my_func()

src/closuresAdv.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#Add arguments to function and check
2+
def outer_function(msg):
3+
message = msg
4+
5+
def inner_function():
6+
print(message)
7+
8+
return inner_function #removed Paranthesis
9+
10+
11+
Hi_func = outer_function('Hi') #MY func is = inner_function(){ready to be executed}
12+
Bye_func = outer_function('Bye')
13+
Hi_func()
14+
Bye_func()

src/decorator_class.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
2+
#Using class as decorators instead of functions
3+
4+
class decorator_class(object):
5+
#How to pass original_function as argument to this class...we will use __init__ method for it
6+
7+
def __init__(self,original_function):
8+
self.original_function = original_function
9+
#Above code has tied our class instance to original function method
10+
11+
#How to add extra functionalities to the original function
12+
#We will use the __call__ method for this with *args and **Kwargs
13+
14+
def __call__(self, *args, **kwargs):
15+
print('call method executed this before {}'.format(self.original_function.__name__))
16+
return self.original_function(*args,**kwargs)
17+
18+
@decorator_class
19+
def display_info(name,age):
20+
print('display_info ran with arguments ({},{})'.format(name,age))
21+
22+
@decorator_class
23+
def display():
24+
print('display function ran!')
25+
26+
27+
display_info("Vipulkumar",19)
28+
display()
29+

src/decorators_2.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
2+
3+
def decorator_function(original_function):
4+
def wrapper_function(*args,**kwargs):
5+
#When we were passing arguments to display_info() and it was wrapped under decorator_functiom
6+
#It throws errors that wrapper function shud not contain arguments
7+
#To add arguments to wrapper function we shud use *args and **kwargs
8+
#That also will run OK with wrapper function with no arguments
9+
10+
print('wrapper executed this before {}'.format(original_function.__name__))
11+
return original_function(*args,**kwargs)
12+
return wrapper_function
13+
14+
@decorator_function
15+
#above line is equal to the following line
16+
# display = decorator_function(display)
17+
def display():
18+
print('Display Function Ran!')
19+
20+
@decorator_function
21+
def display_info(name,age):
22+
print('display_info ran with arguments ({},{})'.format(name,age))
23+
24+
25+
26+
display_info('Vipulkumar',19)
27+
display()
28+
29+

src/decorators_in_python.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
2+
# def decorator_function(message):
3+
# def wrapper_function():
4+
# print(message)
5+
#
6+
# return wrapper_function
7+
#
8+
#
9+
# Hi_func = outer_function('Hi') #MY func is = inner_function(){ready to be executed}
10+
# Bye_func = outer_function('Bye')
11+
# Hi_func()
12+
# Bye_func()
13+
14+
15+
def decorator_function(original_function):
16+
def wrapper_function():
17+
print('wrapper executed this before {}'.format(original_function.__name__))
18+
return original_function()
19+
return wrapper_function
20+
21+
#So basically decorators are those that take a function as input and add some extra lines of code
22+
#or execute some extra lines or add some extra functionalities to existing original function
23+
#anad then return the function without actually modifying the code of the original function
24+
25+
# def display():
26+
# print('Display Function Ran!')
27+
28+
# decorated_display = decorator_function(display)#Returns wrapper fuction ready to be executed
29+
# #decorated_display variable is equal to wrapper function ready to be executed
30+
# decorated_display()
31+
32+
#now if we use
33+
@decorator_function
34+
#above line is equal to the following line
35+
# display = decorator_function(display)
36+
def display():
37+
print('Display Function Ran!')
38+
39+
#now if we call display it will give the modified ones also
40+
display()
41+
#So the wrapper code is added to original function
42+
43+

src/firstclassfunctions.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
def outer_function():
3+
message = 'Hi'
4+
5+
def inner_function():
6+
print(message)
7+
8+
return inner_function()
9+
10+
11+
outer_function()

0 commit comments

Comments
 (0)