Python Lambda, Recursion & Type Hints
A lambda function is a small, anonymous inline function that can have any number of parameters but only a single expression whose evaluated value is automatically returned.
Lambdas are most commonly used as lightweight key functions for sorted(), filter(), and map():
# 1. Basic inline lambda:
square = lambda x: x ** 2
print("Square of 6:", square(6))
# 2. Sorting complex data structures by custom key:
employees = [
{"name": "Balaji", "salary": 95000},
{"name": "Alex", "salary": 65000},
{"name": "Chloe", "salary": 82000}
]
# Sort employees by salary ascending using lambda:
sorted_by_salary = sorted(employees, key=lambda emp: emp["salary"])
print("\nSorted by Salary:")
for emp in sorted_by_salary:
print(f"โข {emp['name']:8}: Rs.{emp['salary']}")
# 3. filter() with lambda:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = list(filter(lambda n: n % 2 == 0, numbers))
print("\nEven Numbers (via filter):", even_numbers)
Lambdas cannot contain assignments (=), loops (for/while), or multiple statements. For complex logic, always define a standard def function.
Recursion is a programming technique where a function calls itself to solve a smaller instance of the same problem.
Every well-structured recursive function requires two components:
- Base Case: The termination condition that stops recursion without making another call.
- Recursive Step: Calling itself with modified arguments moving closer to the base case.
# 1. Factorial Calculation via Recursion (n! = n * (n-1)!)
def factorial(n):
# Base Case:
if n <= 1:
return 1
# Recursive Step:
return n * factorial(n - 1)
# 2. Fibonacci Sequence via Recursion:
def fibonacci(n):
if n <= 0: return 0
if n == 1: return 1
return fibonacci(n - 1) + fibonacci(n - 2)
print("Factorial of 5 (5!):", factorial(5)) # 120
print("Fibonacci #7:", fibonacci(7)) # 13
CPython protects your computer RAM with a default maximum recursion limit of 1000 frames (sys.getrecursionlimit()) to prevent stack overflow crashes.
Introduced in Python 3.5+ (PEP 484), Type Hints allow you to annotate expected parameter types and return types. Type hints do not impact runtime speed, but enable instant IDE autocomplete, static bug detection with tools like mypy, and self-documenting codebases:
from typing import List, Dict, Optional, Tuple
def calculate_student_gpa(
scores: List[float],
student_id: int,
extra_credit: Optional[float] = None
) -> Tuple[float, str]:
"""Calculate GPA and return formatted tuple."""
total = sum(scores) + (extra_credit or 0.0)
gpa = total / len(scores)
status = "Pass" if gpa >= 50.0 else "Fail"
return round(gpa, 2), status
gpa, status = calculate_student_gpa([85.0, 92.5, 78.0], 101, extra_credit=5.0)
print(f"Student GPA: {gpa} | Status: {status}")
scores: List[float]specifies a list of decimal floats.-> Tuple[float, str]clearly documents the returned pair.
A customizable, cryptographically strong random password generator using functions and standard library modules:
import random
import string
def generate_secure_password(
length: int = 12,
include_uppercase: bool = True,
include_digits: bool = True,
include_special: bool = True
) -> str:
"""Generate a randomized secure password based on complexity rules."""
char_pool = string.ascii_lowercase
password_chars = [random.choice(string.ascii_lowercase)]
if include_uppercase:
char_pool += string.ascii_uppercase
password_chars.append(random.choice(string.ascii_uppercase))
if include_digits:
char_pool += string.digits
password_chars.append(random.choice(string.digits))
if include_special:
special_chars = "!@#$%^&*()-_=+"
char_pool += special_chars
password_chars.append(random.choice(special_chars))
# Fill remaining characters randomly from the combined pool:
for _ in range(length - len(password_chars)):
password_chars.append(random.choice(char_pool))
# Shuffle to eliminate predictable character positioning:
random.shuffle(password_chars)
return "".join(password_chars)
# Generate various password profiles:
print("๐ 12-char Standard Password:", generate_secure_password(12))
print("๐ 16-char Ultra-Secure: ", generate_secure_password(16))
print("๐ 8-char Digits-Only Pin: ", generate_secure_password(8, include_uppercase=False, include_special=False))
We guarantee at least one character of each requested type, and then execute random.shuffle() so the characters appear in completely unpredictable positions.
If your recursive function lacks a terminating base case, it will call itself endlessly until CPython crashes with RecursionError: maximum recursion depth exceeded. Always define base cases first!
Use a lambda function with sorted() to sort a list of city tuples by their temperature (2nd element) in descending order.
weather_data = [("Hyderabad", 34), ("Bengaluru", 24), ("Delhi", 40), ("Shimla", 16)]
sorted_cities = sorted(weather_data, key=lambda item: item[1], reverse=True)
print("Hottest to Coldest Cities:")
for city, temp in sorted_cities:
print(f"โข {city:10}: {temp}ยฐC")
Q When should I use a lambda function instead of def?
Use lambda for simple, disposable, single-line functions passed directly into higher-order functions like sorted(key=...), filter(), or map(). If logic spans multiple statements or needs reuse, use def.
Q Do Python type hints enforce type safety at runtime?
No. Python remains dynamically typed and will not crash at runtime if a mismatched type is passed. Type hints are used by IDEs, linters, and static analyzers (mypy) to catch bugs during development.
Q What is tail call optimization, and does Python support it?
Tail call optimization replaces recursive stack frames with loops to prevent stack overflow. Guido van Rossum intentionally omitted tail call optimization from CPython to preserve complete debug stack traces.