This repository contains different projects.
The projects focus on advanced Python concepts, testing, and backend development practices.
This repository covers the following major topics:
- Unit Tests and Integration Tests
- Context Managers
- Decorators
- Generators
- Asynchronous Programming (async/await)
Each topic is explained separately below.
- Unit testing: Test individual functions in isolation. External dependencies (e.g., databases, APIs) should be mocked.
- Integration testing: Test how multiple components interact together, mocking only external requests.
- Ensures reliability of functions.
- Protects against regressions.
- Encourages modular and maintainable code.
A context manager handles setup and cleanup actions automatically (e.g., opening/closing a file). They are commonly used with the with statement.
with open("data.txt", "r") as f:
content = f.read()
# file is automatically closed here
class MyContext:
def __enter__(self):
print("Entering context")
return self
def __exit__(self, exc_type, exc_value, traceback):
print("Exiting context")
with MyContext():
print("Inside block")
🔹 What They Are
A decorator is a function that takes another function and extends its behavior without modifying it.
def wrapper():
print("Before function call")
func()
print("After function call")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
@memoize in utils.py is a decorator that caches method results.
🔹 What They Are
A generator is a function that yields values one at a time using yield, instead of returning them all at once.
def count_up_to(n):
i = 1
while i <= n:
yield i
i += 1
for num in count_up_to(5):
print(num)
Saves memory (lazy evaluation).
Perfect for streaming data or infinite sequences.
Asynchronous programming allows multiple tasks to run concurrently without blocking each other. Python uses async and await keywords for this.
import asyncio
async def say_hello():
await asyncio.sleep(1)
print("Hello async!")
async def main():
await asyncio.gather(say_hello(), say_hello())
asyncio.run(main())
Essential for backend services handling multiple requests.
Efficient handling of I/O-bound operations (APIs, databases).