Skip to content

Commit 974c780

Browse files
authored
Merge pull request #14 from codeasarjun/deco
Deco
2 parents f08caa5 + f0c9e40 commit 974c780

File tree

6 files changed

+143
-0
lines changed

6 files changed

+143
-0
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
## What is a Decorator?
2+
3+
A decorator is a special type of function that takes another function as an argument and extends or alters its behavior. This is achieved by defining a wrapper function inside the decorator that wraps around the original function. Decorators are commonly used for:
4+
5+
- **Logging:** Automatically log function calls, arguments, and results.
6+
- **Timing:** Measure the execution time of functions.
7+
- **Authentication:** Restrict access to functions based on user credentials.
8+
- **Caching:** Store and retrieve results of expensive function calls to improve performance.
9+
- **Rate Limiting:** Control how frequently a function can be called.
10+
11+
## Why Use Decorators?
12+
13+
Decorators offer several benefits:
14+
15+
- **Code Reusability:** Define functionality once and apply it to multiple functions or methods.
16+
- **Separation of Concerns:** Keep the core logic of functions separate from cross-cutting concerns like logging or authentication.
17+
- **Maintainability:** Easier to modify or extend functionality without changing the original function code.
18+
- **Readability:** Enhances the readability and organization of your code.
19+
20+
## File Descriptions
21+
22+
### `decorators_example.py`
23+
24+
This file contains various decorator implementations.
25+
26+
- **`log_function_call`**: Logs details of function calls, including arguments and results.
27+
- **`timing_decorator`**: Measures and prints the execution time of functions.
28+
- **`requires_authentication`**: Restricts access to functions based on user authentication status.
29+
- **`cache_results`**: Caches function results to improve performance.
30+
- **`rate_limit`**: Limits the frequency of function calls to prevent rate limiting issues.
31+
32+
33+
## dec_call_functions.py
34+
35+
This file contains functions that utilize the decorators from `decorators_example.py`. It demonstrates how to apply various decorators to functions to enhance their functionality.
36+
37+
- **add:** A simple function to add two numbers, with logging applied.
38+
- **compute_square:** Computes the square of numbers up to `n`, with timing applied.
39+
- **view_profile:** Displays a user profile if authenticated, with authentication applied.
40+
- **fibonacci:** Computes the Fibonacci sequence, with result caching applied.
41+
- **fetch_data:** Retrieves data with rate limiting applied.
42+
43+
Binary file not shown.
Binary file not shown.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
2+
from decorators_example import log_function_call, timing_decorator, requires_authentication, cache_results, rate_limit
3+
4+
@log_function_call
5+
def add(a, b):
6+
return a + b
7+
8+
@timing_decorator
9+
def compute_square(n):
10+
return [i ** 2 for i in range(n)]
11+
12+
@requires_authentication
13+
def view_profile(user):
14+
return f"Welcome to your profile, {user['name']}!"
15+
16+
@cache_results
17+
def fibonacci(n):
18+
if n <= 1:
19+
return n
20+
return fibonacci(n - 1) + fibonacci(n - 2)
21+
22+
@rate_limit(max_calls=1, period=5)
23+
def fetch_data():
24+
return "Data fetched successfully!"
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# decorators.py
2+
3+
import time
4+
import logging
5+
from functools import wraps
6+
7+
# Configure logging
8+
logging.basicConfig(level=logging.INFO)
9+
10+
def log_function_call(func):
11+
@wraps(func)
12+
def wrapper(*args, **kwargs):
13+
logging.info(f"Calling function '{func.__name__}' with arguments {args} and keyword arguments {kwargs}")
14+
result = func(*args, **kwargs)
15+
logging.info(f"Function '{func.__name__}' returned {result}")
16+
return result
17+
return wrapper
18+
19+
def timing_decorator(func):
20+
@wraps(func)
21+
def wrapper(*args, **kwargs):
22+
start_time = time.time()
23+
result = func(*args, **kwargs)
24+
end_time = time.time()
25+
execution_time = end_time - start_time
26+
print(f"Function '{func.__name__}' took {execution_time:.4f} seconds to execute")
27+
return result
28+
return wrapper
29+
30+
def requires_authentication(func):
31+
@wraps(func)
32+
def wrapper(user, *args, **kwargs):
33+
if not user.get('authenticated'):
34+
return "Access Denied: User not authenticated"
35+
return func(user, *args, **kwargs)
36+
return wrapper
37+
38+
def cache_results(func):
39+
cache = {}
40+
@wraps(func)
41+
def wrapper(*args, **kwargs):
42+
if args in cache:
43+
return cache[args]
44+
result = func(*args, **kwargs)
45+
cache[args] = result
46+
return result
47+
return wrapper
48+
49+
def rate_limit(max_calls, period):
50+
def decorator(func):
51+
last_called = [0]
52+
@wraps(func)
53+
def wrapper(*args, **kwargs):
54+
current_time = time.time()
55+
if current_time - last_called[0] < period:
56+
return "Rate limit exceeded. Please try again later."
57+
last_called[0] = current_time
58+
return func(*args, **kwargs)
59+
return wrapper
60+
return decorator
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import time
2+
from dec_call_functions import add, compute_square, view_profile, fibonacci, fetch_data
3+
4+
if __name__ == "__main__":
5+
print(add(5, 7))
6+
compute_square(1000000)
7+
user1 = {'name': 'Alice', 'authenticated': True}
8+
user2 = {'name': 'Bob', 'authenticated': False}
9+
print(view_profile(user1))
10+
print(view_profile(user2))
11+
print(fibonacci(10))
12+
print(fetch_data())
13+
time.sleep(3)
14+
print(fetch_data())
15+
time.sleep(5)
16+
print(fetch_data())

0 commit comments

Comments
 (0)