
Python
Professional Python code balances flexibility with clarity. Using type hints, following PEP 8, validating inputs, handling errors gracefully, and documenting types creates maintainable, debuggable applications. These practices become increasingly important in team environments and long-lived codebases.
Type hints serve as executable documentation, enabling static type checking and IDE support.
from typing import Optional, Union, List, Dict, Callable
# Document parameter and return types
def process_user(
user_id: int,
include_details: bool = False
) -> Dict[str, Union[int, str, bool]]:
"""
Process user and return user data.
Args:
user_id: User ID (must be positive)
include_details: Include detailed information
Returns:
Dictionary with user data
Raises:
ValueError: If user_id <= 0
UserNotFoundError: If user doesn't exist
"""
if user_id <= 0:
raise ValueError("user_id must be positive")
# Implementation...
# Optional types (can be None)
def find_user(email: str) -> Optional[Dict]:
# Could return dict or None
pass
# Union types (multiple possibilities)
def convert_to_number(value: Union[str, int, float]) -> float:
return float(value)
# Callable types
def apply_to_list(items: List[int], func: Callable[[int], int]) -> List[int]:
return [func(item) for item in items]
# Use mypy for type checking
# pip install mypy
# mypy your_file.pyAlways validate data at system boundaries (user input, external APIs, file I/O).
class ValidationError(Exception):
"""Raised when validation fails."""
pass
def create_user(name: str, age: int, email: str) -> Dict:
"""Create user with validation."""
# Type validation
if not isinstance(name, str):
raise TypeError("name must be string")
if not isinstance(age, int):
raise TypeError("age must be int")
# Value validation
if not name or len(name) < 2:
raise ValidationError("name must be 2+ characters")
if age < 0 or age > 150:
raise ValidationError("age must be 0-150")
if '@' not in email:
raise ValidationError("invalid email")
return {"name": name, "age": age, "email": email}
# Safe conversion with defaults
def safe_int(value, default=0) -> int:
"""Convert to int with fallback."""
try:
return int(value)
except (ValueError, TypeError):
return default
# Graceful error handling
try:
user_data = create_user("Alice", "25", "alice@example.com")
except (TypeError, ValidationError) as e:
print(f"Invalid user data: {e}")
user_data = None# Dataclass for structured data (Python 3.7+)
from dataclasses import dataclass
@dataclass
class User:
name: str
age: int
email: str
def __post_init__(self):
"""Validate after initialization."""
if len(self.name) < 2:
raise ValueError("name must be 2+ characters")
# Use constants for magic values
class Config:
MAX_RETRIES = 3
TIMEOUT_SECONDS = 30
DEFAULT_ENCODING = 'utf-8'
def api_call(url: str, retries: int = Config.MAX_RETRIES):
"""Make API call with retry logic."""
pass
# Context manager for resource management
from contextlib import contextmanager
@contextmanager
def timer():
"""Context manager for timing code."""
import time
start = time.time()
try:
yield
finally:
elapsed = time.time() - start
print(f"Elapsed: {elapsed:.2f}s")
with timer():
# Code is timed
pass
# Property for computed attributes
class Rectangle:
def __init__(self, width: float, height: float):
self.width = width
self.height = height
@property
def area(self) -> float:
"""Compute area on demand."""
return self.width * self.height
@property
def perimeter(self) -> float:
"""Compute perimeter on demand."""
return 2 * (self.width + self.height)# Use appropriate data structures
# Bad: searching list repeatedly
items = [1, 2, 3, 4, 5]
if 3 in items: # O(n) operation
pass
# Good: use set for membership testing
items_set = {1, 2, 3, 4, 5}
if 3 in items_set: # O(1) operation
pass
# String concatenation
# Bad: creates new strings repeatedly
result = ""
for item in items:
result += str(item)
# Good: use join (single operation)
result = "".join(str(item) for item in items)
# Generator expressions for large datasets
# Bad: creates full list in memory
squares = [x**2 for x in range(1000000)]
# Good: generator (lazy evaluation)
squares_gen = (x**2 for x in range(1000000))
# Use __slots__ for memory efficiency
class Point:
__slots__ = ['x', 'y'] # Fixed attributes
def __init__(self, x, y):
self.x = x
self.y = y# Unit test for type handling
import unittest
class TestUserCreation(unittest.TestCase):
def test_valid_user(self):
user = create_user("Alice", 25, "alice@example.com")
self.assertEqual(user['name'], "Alice")
def test_invalid_age(self):
with self.assertRaises(ValidationError):
create_user("Alice", 200, "alice@example.com")
def test_invalid_email(self):
with self.assertRaises(ValidationError):
create_user("Alice", 25, "invalid-email")
# Property-based testing
from hypothesis import given, strategies as st
@given(st.integers(min_value=0, max_value=150))
def test_age_validation(age):
"""Test age validation with random values."""
user = create_user("Alice", age, "alice@example.com")
assert user['age'] == ageā
Use type hints for all public functions
ā
Follow PEP 8 style guide
ā
Validate inputs at system boundaries
ā
Handle errors gracefully
ā
Document expected types and exceptions
ā
Use appropriate data structures
ā
Avoid mutable default arguments
ā
Use constants for magic values
ā
Test with various inputs
ā
Use immutable objects when possible
ā
Profile before optimizing
ā
Document assumptionsCongratulations! You now understand:
You're now a Variables & Data Types expert! š
Ready to apply your knowledge? Try advanced challenges or take the quiz
Resources
Ojasa Mirai
Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.
Learn Deep ⢠Build Real ⢠Verify Skills ⢠Launch Forward