Table of Contents

  1. Python Basics
  2. OOP Concepts
  3. Python Advanced Topics
  4. AWS
  5. Scenario-Based Questions
  6. Coding Questions
  7. System Design
  8. Flask/Django
  9. REST APIs
  10. Databases
  11. Testing
  12. Concurrency
  13. Hashing
  14. Other Topics

Python Basics

Questions and Answers

Q: What is the main purpose of a constructor in OOP?
A:

  • Primary role: Initialize object state with default/initial values
  • Called automatically during object instantiation
  • In Python, implemented via __init__ method
  • Enables encapsulation by validating initial data
class User:
    def __init__(self, name: str, id: int):
        self.name = name  # Initialize instance variables
        self.id = id

Q: Which data types are hashable in Python?
A:

HashableNon-Hashable
int, float, boollist, dict
strset
tuple (if immutable)bytearray
frozensetcustom objects*

*Objects are hashable if they implement __hash__ and __eq__ methods

Q: What is the role of __name__ in Flask applications?
A:

  • Special Python variable storing module name
  • Helps Flask locate:
    • Template directories
    • Static assets
    • Root path for relative file paths
  • Critical for proper app initialization:
    app = Flask(__name__)

Q: How does file uploading work in Flask?
A:

  1. Client sends multipart/form-data request
  2. Access files via request.files dictionary
  3. Security considerations:
    • Limit file extensions (ALLOWED_EXTENSIONS)
    • Validate content type
    • Store in secure location
@app.route('/upload', methods=['POST'])
def upload_file():
    file = request.files['file']
    if file and allowed_file(file.filename):
        file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))

Q: What is Flask-JWT?
A:

  • Extension for JSON Web Token authentication
  • Typical workflow:
    1. User logs in β†’ returns access token
    2. Token sent in Authorization header
    3. Protected routes verify token
  • Key features:
    • Token expiration
    • Refresh tokens
    • Blacklist management
from flask import Flask, jsonify, request
from flask_jwt import JWT, jwt_required, current_identity
from werkzeug.security import safe_str_cmp
 
# Sample user database (replace with real database in production)
users = {
    "user1": {
        "username": "user1",
        "password": "password1"  # In real app, use hashed passwords
    }
}
 
class User(object):
    def __init__(self, username):
        self.username = username
 
# Flask app setup
app = Flask(__name__)
app.secret_key = 'super-secret-key'  # Replace with actual secret key
 
# JWT authentication setup
def authenticate(username, password):
    user = users.get(username)
    if user and safe_str_cmp(user['password'], password):
        return User(username)
 
def identity(payload):
    username = payload['identity']
    return users.get(username)
 
jwt = JWT(app, authenticate, identity)
 
# Protected route
@app.route('/protected')
@jwt_required()
def protected():
    return jsonify({'message': f'Hello {current_identity.username}! This is a protected route'})
 
# Login endpoint (automatically created by Flask-JWT at /auth)
# curl -X POST -H "Content-Type: application/json" -d '{"username":"user1","password":"password1"}' http://localhost:5000/auth
 
# Example usage
if __name__ == '__main__':
    app.run(debug=True)

OOP Concepts

Questions and Answers

Q: Explain the diamond problem in multiple inheritance
A:

  • Occurs when class inherits from two classes sharing a common ancestor
  • Python resolves using MRO (Method Resolution Order) with C3 linearization
  • Example resolution order: Child β†’ Parent1 β†’ Parent2 β†’ Grandparent
class Grandparent:
    def method(self):
        print("Grandparent")
 
class Parent1(Grandparent):
    def method(self):
        print("Parent1")
 
class Parent2(Grandparent):
    def method(self):
        print("Parent2")
 
class Child(Parent1, Parent2):
    pass
 
# MRO: Child β†’ Parent1 β†’ Parent2 β†’ Grandparent

Python Advanced Topics

Questions and Answers

Q: How can you implement a custom iterator?
A:

  1. Implement __iter__ returning self
  2. Implement __next__ with iteration logic
  3. Raise StopIteration when complete
class CountDown:
    def __init__(self, start):
        self.current = start
 
    def __iter__(self):
        return self
 
    def __next__(self):
        if self.current <= 0:
            raise StopIteration
        num = self.current
        self.current -= 1
        return num
 
# Usage:
for num in CountDown(5):
    print(num)  # 5,4,3,2,1

Q: What is the Global Interpreter Lock (GIL)?
A:

  • Mutex protecting Python object access
  • Impacts:
    • Allows only one thread execution at a time
    • Limits CPU-bound multithreading performance
    • Doesn’t affect I/O-bound operations
  • Workarounds:
    • Multiprocessing
    • Asyncio for I/O tasks
    • C extensions releasing GIL

AWS

Questions and Answers

Q: How would you secure S3 buckets?
A:

  • Access control methods:
    • IAM policies (principle of least privilege)
    • Bucket policies (resource-based)
    • ACLs (legacy, avoid)
    • Presigned URLs for temporary access
  • Encryption:
    • SSE-S3, SSE-KMS, SSE-C
    • Client-side encryption
  • Monitoring:
    • Enable S3 access logging
    • Use CloudTrail for API tracking
    • Set up Config rules for compliance

Q: Explain Lambda cold starts
A:

  • Initialization phase when no idle instances available
  • Factors affecting duration:
    • Runtime (Python < Java)
    • Package size
    • VPC configuration
  • Mitigation strategies:
    • Provisioned concurrency
    • Keep packages lean
    • Avoid VPCs when possible
    • Periodic ping (keep-warm)

Coding Questions

Add Two Numbers (LeetCode Optimized)

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
 
def addTwoNumbers(l1: ListNode, l2: ListNode) -> ListNode:
    """
    Time Complexity: O(max(m,n))
    Space Complexity: O(max(m,n))
    """
    dummy = ListNode()  # Anchor node for result
    current = dummy
    carry = 0
    
    while l1 or l2 or carry:
        # Calculate sum of current digits
        val1 = l1.val if l1 else 0
        val2 = l2.val if l2 else 0
        total = val1 + val2 + carry
        
        # Update carry and create new node
        carry, digit = divmod(total, 10)
        current.next = ListNode(digit)
        current = current.next
        
        # Move to next nodes if available
        l1 = l1.next if l1 else None
        l2 = l2.next if l2 else None
    
    return dummy.next

Optimized Zero Sorting

def move_zeros_and_sort(arr: list) -> list:
    """
    Time Complexity: O(n log n) due to sort
    Space Complexity: O(n)
    """
    # Partition zeros and non-zeros in single pass
    zeros_count = 0
    non_zeros = []
    for num in arr:
        if num == 0:
            zeros_count += 1
        else:
            non_zeros.append(num)
    
    # In-place sort for memory efficiency
    non_zeros.sort()
    return [0]*zeros_count + non_zeros

System Design

Task Scheduler API Design

Key Components:

  1. Authentication: JWT with refresh tokens
  2. Authorization: RBAC (User/Admin roles)
  3. Endpoints:
    POST /api/tasks       - Create task
    GET /api/tasks?status=active - Filter tasks
    PUT /api/tasks/{id}   - Update task
    DEL /api/tasks/{id}   - Delete task
    POST /api/tasks/reminders - Set reminder
    
  4. Database Schema:
    CREATE TABLE tasks (
        id UUID PRIMARY KEY,
        user_id UUID REFERENCES users(id),
        title VARCHAR(255),
        status ENUM('pending', 'completed'),
        due_date TIMESTAMP,
        created_at TIMESTAMP DEFAULT NOW()
    );
  5. Scalability:
    • Use Redis for rate limiting
    • Celery for async reminders
    • Sharding by user_id for horizontal scaling

Flask/Django

Questions and Answers

Q: Flask vs Django Middleware
A:

FeatureFlaskDjango
Middleware TypeDecorator-basedClass-based
Execution OrderRoute-specificGlobal
FlexibilityHighStructured
Common UsesAuth, LoggingCSRF, Session

Q: Optimize Flask Performance
A:

  • Use production server (Gunicorn/uWSGI)
  • Enable JIT compilation with PyPy
  • Database optimizations:
    • Connection pooling
    • Index optimization
    • Query caching
  • Enable compression with Flask-Compress
  • Use CDN for static assets

REST APIs

Best Practices

  1. Versioning: /api/v1/resource
  2. Pagination: ?page=2&limit=50
  3. Filtering: ?status=active&sort=-created_at
  4. HATEOAS: Include resource links
  5. Rate Limiting: X-RateLimit headers
  6. Error Handling:
{
    "error": "InvalidRequest",
    "message": "Missing required field: email",
    "code": 400
}

Databases

Connection Pooling Pattern

from sqlalchemy import create_engine
from sqlalchemy.pool import QueuePool
 
engine = create_engine(
    'postgresql://user:pass@host/db',
    poolclass=QueuePool,
    pool_size=10,
    max_overflow=5,
    pool_timeout=30
)

Testing

Pytest Fixture Example

import pytest
 
@pytest.fixture
def db_connection():
    conn = create_test_connection()
    yield conn  # Setup/teardown
    conn.close()
 
def test_query(db_connection):
    result = db_connection.execute("SELECT 1")
    assert result.fetchone() == (1,)

Concurrency

Thread Pool Pattern

from concurrent.futures import ThreadPoolExecutor
 
def process_data(data):
    # CPU-intensive work
 
with ThreadPoolExecutor(max_workers=4) as executor:
    futures = [executor.submit(process_data, chunk) 
              for chunk in data_chunks]
    results = [f.result() for f in futures]

Hashing

Secure Password Handling

from werkzeug.security import generate_password_hash, check_password_hash
 
hashed_pw = generate_password_hash('secret', method='pbkdf2:sha512')
is_valid = check_password_hash(hashed_pw, 'secret')  # Returns bool

Other Topics

CI/CD Pipeline

graph LR
A[Git Commit] --> B[Run Tests]
B --> C{Build Docker}
C -->|Success| D[Deploy Staging]
D --> E[Integration Tests]
E --> F{Manual Approval}
F --> G[Deploy Prod]