Skip to content

Commit 16bcd8e

Browse files
committed
Add decorators for timing, debugging, and caching function results; enhance closure examples and add image asset
1 parent 3196be3 commit 16bcd8e

File tree

3 files changed

+163
-0
lines changed

3 files changed

+163
-0
lines changed

Decoraters/decoraters.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#Question No 1.
2+
import time
3+
4+
# Decorator to calculate execution time
5+
def timer(func):
6+
def wrapper(*args, **kwargs):
7+
start = time.time() # Record start time
8+
result = func(*args, **kwargs) # Call the actual function
9+
end = time.time() # Record end time
10+
print(f"{func.__name__} ran in {end - start:.4f} seconds")
11+
return result
12+
return wrapper
13+
14+
@timer
15+
def example_function(n):
16+
time.sleep(n) # Simulate a long task
17+
18+
example_function(2) # OUTPUT: example_function ran in 2.00XX seconds
19+
20+
21+
#Question No 2.
22+
# Decorator to debug function call
23+
def debug(func):
24+
def wrapper(*args, **kwargs):
25+
args_value = ', '.join(str(arg) for arg in args)
26+
kwargs_value = ', '.join(f"{k}={v}" for k, v in kwargs.items())
27+
print(f"Calling: {func.__name__} with args ({args_value}) and kwargs {{{kwargs_value}}}")
28+
return func(*args, **kwargs)
29+
return wrapper
30+
31+
@debug
32+
def greet(name, greeting="Hello"):
33+
print(f"{greeting}, {name}!")
34+
35+
greet("chai", greeting="hanji")
36+
# OUTPUT:
37+
# Calling: greet with args (chai) and kwargs {greeting=hanji}
38+
# hanji, chai!
39+
40+
41+
42+
#Question No 3.
43+
import time
44+
45+
# Decorator to cache function results
46+
def cache(func):
47+
cache_value = {} # Dictionary to store previous results
48+
def wrapper(*args):
49+
if args in cache_value:
50+
print(f"Fetching from cache for {args}")
51+
return cache_value[args]
52+
print(f"Computing result for {args}")
53+
result = func(*args)
54+
cache_value[args] = result # Save result to cache
55+
return result
56+
return wrapper
57+
58+
@cache
59+
def long_running_function(a, b):
60+
time.sleep(4) # Simulate expensive computation
61+
return a + b
62+
63+
print(long_running_function(2, 3)) # Takes 4 seconds first time
64+
print(long_running_function(2, 3)) # Instant the second time
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# ✅ Example 1: Global Variable Usage
2+
a = 5
3+
4+
def function():
5+
global a # Use the global 'a' instead of creating a local one
6+
print("Before changing, a =", a) # Should print 5
7+
a = 10 # Update global variable 'a'
8+
print("After changing, a =", a) # Should print 10
9+
10+
function()
11+
print("Global a after function call:", a) # Confirm global 'a' is now 10
12+
13+
14+
# ✅ Example 2: Closure Example – Function Inside a Function
15+
def f1():
16+
x = 88 # This is in the enclosing scope of f2
17+
def f2():
18+
print("Value from closure:", x) # f2 uses x from f1
19+
return f2 # Return the inner function
20+
21+
myResult = f1() # myResult now holds reference to f2, with access to x=88
22+
myResult() # Should print: Value from closure: 88
23+
24+
25+
# ✅ Example 3: Function Factory using Closure
26+
def chaicoder(num): # Outer function with parameter `num`
27+
def actual(x): # Inner function that uses `num` from outer scope
28+
return x ** num
29+
return actual # Return the inner function
30+
31+
f = chaicoder(2) # f becomes a function that squares numbers
32+
g = chaicoder(3) # g becomes a function that cubes numbers
33+
34+
print("Function f (square):", f) # Prints function reference
35+
print("Function g (cube):", g) # Prints function reference
36+
37+
print("f(3) =", f(3)) # 3^2 = 9
38+
print("g(3) =", g(3)) # 3^3 = 27
39+
40+
41+
42+
# Closure to keep track of count
43+
def counter():
44+
count = 0
45+
def increment():
46+
nonlocal count # Use 'nonlocal' to modify the outer function variable
47+
count += 1
48+
return count
49+
return increment
50+
51+
count1 = counter()
52+
print(count1()) # 1
53+
print(count1()) # 2
54+
55+
count2 = counter()
56+
print(count2()) # 1 (separate instance)
57+
print(count1()) # 3 (continues from previous count1)
58+
59+
#Add-On 2: Lambda with Closure
60+
def power_maker(n):
61+
return lambda x: x ** n # Returns an anonymous function that remembers n
62+
63+
square = power_maker(2)
64+
cube = power_maker(3)
65+
66+
print("square(4) =", square(4)) # 16
67+
print("cube(2) =", cube(2)) # 8
68+
69+
70+
#Add-On 3: Function Scope vs Global vs Nonlocal
71+
72+
x = "global"
73+
74+
def outer():
75+
x = "outer"
76+
def inner():
77+
nonlocal x
78+
x = "inner"
79+
print("Inner:", x)
80+
inner()
81+
print("Outer after inner:", x)
82+
83+
outer()
84+
print("Global:", x)
85+
86+
87+
88+
#Add-On 4: Common Mistake in Closures in Loops (Late Binding)
89+
functions = []
90+
91+
for i in range(3):
92+
def make_func(n):
93+
def f():
94+
print(n)
95+
return f
96+
functions.append(make_func(i))
97+
98+
for fn in functions:
99+
fn() # Correct: prints 0, 1, 2

scope_and_clousers/image.png

95.5 KB
Loading

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy