python-by-example/05_functions/01_function_basics.py
2025-12-30 08:50:00 +02:00

338 lines
9.6 KiB
Python

"""
================================================================================
File: 01_function_basics.py
Topic: Python Functions - Basic Concepts
================================================================================
This file demonstrates the fundamentals of functions in Python. Functions
are reusable blocks of code that perform specific tasks, making your code
more organized, readable, and maintainable.
Key Concepts:
- Defining functions with def
- Calling functions
- Function documentation (docstrings)
- Variable scope (local vs global)
- Basic parameters
================================================================================
"""
# -----------------------------------------------------------------------------
# 1. Defining and Calling Functions
# -----------------------------------------------------------------------------
# Use 'def' keyword to define a function
print("--- Defining and Calling Functions ---")
# Simple function with no parameters
def greet():
"""Print a greeting message."""
print("Hello, World!")
# Call the function
greet()
# Function with a parameter
def greet_person(name):
"""Greet a specific person."""
print(f"Hello, {name}!")
greet_person("Baraa")
greet_person("Sara")
# -----------------------------------------------------------------------------
# 2. Function with Multiple Parameters
# -----------------------------------------------------------------------------
print("\n--- Multiple Parameters ---")
def introduce(name, age, city):
"""Introduce a person with their details."""
print(f"My name is {name}, I am {age} years old, and I live in {city}.")
introduce("Ali", 25, "Cairo")
# -----------------------------------------------------------------------------
# 3. Return Values
# -----------------------------------------------------------------------------
# Functions can return values using 'return'
print("\n--- Return Values ---")
def add(a, b):
"""Add two numbers and return the result."""
return a + b
result = add(5, 3)
print(f"5 + 3 = {result}")
# Using returned value in expressions
total = add(10, 20) + add(5, 5)
print(f"(10+20) + (5+5) = {total}")
# Function without explicit return returns None
def print_message(msg):
print(msg)
result = print_message("Hello")
print(f"Function without return: {result}") # None
# Early return
def get_grade(score):
"""Return letter grade based on score."""
if score >= 90:
return "A"
if score >= 80:
return "B"
if score >= 70:
return "C"
if score >= 60:
return "D"
return "F"
print(f"\nScore 85 → Grade {get_grade(85)}")
# -----------------------------------------------------------------------------
# 4. Docstrings - Function Documentation
# -----------------------------------------------------------------------------
# Use triple quotes to document what a function does
print("\n--- Docstrings ---")
def calculate_area(length, width):
"""
Calculate the area of a rectangle.
Args:
length: The length of the rectangle (positive number)
width: The width of the rectangle (positive number)
Returns:
The area of the rectangle (length * width)
Example:
>>> calculate_area(5, 3)
15
"""
return length * width
# Access docstring
print(f"Function docstring:\n{calculate_area.__doc__}")
# Using help()
# help(calculate_area) # Uncomment to see full help
# -----------------------------------------------------------------------------
# 5. Variable Scope - Local vs Global
# -----------------------------------------------------------------------------
# Variables inside functions are local by default
print("\n--- Variable Scope ---")
global_var = "I am global"
def demonstrate_scope():
"""Demonstrate variable scope."""
local_var = "I am local"
print(f" Inside function - global_var: {global_var}")
print(f" Inside function - local_var: {local_var}")
demonstrate_scope()
print(f"Outside function - global_var: {global_var}")
# print(local_var) # This would cause an error!
# Modifying global variables inside functions
counter = 0
def increment_counter():
"""Increment the global counter."""
global counter # Declare we want to modify global variable
counter += 1
print(f" Counter inside function: {counter}")
print(f"\nCounter before: {counter}")
increment_counter()
increment_counter()
print(f"Counter after: {counter}")
# Local variable shadows global
value = 100
def shadow_example():
"""Local variable shadows global."""
value = 200 # This is a new local variable, not the global one
print(f" Inside function: {value}")
print(f"\nGlobal value: {value}")
shadow_example()
print(f"Global value unchanged: {value}")
# -----------------------------------------------------------------------------
# 6. Multiple Return Values
# -----------------------------------------------------------------------------
# Functions can return multiple values as a tuple
print("\n--- Multiple Return Values ---")
def get_min_max(numbers):
"""Return both minimum and maximum of a list."""
return min(numbers), max(numbers)
data = [5, 2, 8, 1, 9, 3]
minimum, maximum = get_min_max(data)
print(f"List: {data}")
print(f"Min: {minimum}, Max: {maximum}")
# Return multiple named values using dictionary
def analyze_text(text):
"""Analyze text and return statistics."""
return {
"length": len(text),
"words": len(text.split()),
"uppercase": sum(1 for c in text if c.isupper())
}
stats = analyze_text("Hello World! How Are You?")
print(f"\nText stats: {stats}")
# -----------------------------------------------------------------------------
# 7. Pass Statement - Placeholder Functions
# -----------------------------------------------------------------------------
# Use pass to create empty function bodies
print("\n--- Placeholder Functions ---")
def future_feature():
"""This will be implemented later."""
pass # Placeholder - does nothing
def another_placeholder():
"""Placeholder with ellipsis (also valid)."""
... # Alternative to pass
future_feature() # Can be called, just does nothing
print("Placeholder functions work!")
# -----------------------------------------------------------------------------
# 8. Nested Functions
# -----------------------------------------------------------------------------
# Functions can be defined inside other functions
print("\n--- Nested Functions ---")
def outer_function(message):
"""Outer function that contains an inner function."""
def inner_function():
"""Inner function that uses outer's variable."""
print(f" Inner says: {message}")
print("Outer function called")
inner_function()
outer_function("Hello from outer!")
# Inner function not accessible outside
# inner_function() # This would cause an error!
# Practical example: Helper function
def calculate_statistics(numbers):
"""Calculate various statistics using helper functions."""
def mean(nums):
return sum(nums) / len(nums)
def variance(nums):
avg = mean(nums)
return sum((x - avg) ** 2 for x in nums) / len(nums)
return {
"mean": mean(numbers),
"variance": variance(numbers),
"std_dev": variance(numbers) ** 0.5
}
data = [2, 4, 4, 4, 5, 5, 7, 9]
stats = calculate_statistics(data)
print(f"\nStatistics for {data}:")
for key, value in stats.items():
print(f" {key}: {value:.2f}")
# -----------------------------------------------------------------------------
# 9. Functions as Objects
# -----------------------------------------------------------------------------
# In Python, functions are first-class objects
print("\n--- Functions as Objects ---")
def say_hello(name):
"""Just say hello."""
return f"Hello, {name}!"
# Assign function to variable
greeting_func = say_hello
print(greeting_func("World"))
# Store functions in a list
def add_one(x): return x + 1
def double(x): return x * 2
def square(x): return x * x
operations = [add_one, double, square]
value = 5
print(f"\nApplying operations to {value}:")
for func in operations:
print(f" {func.__name__}({value}) = {func(value)}")
# Pass function as argument
def apply_operation(func, value):
"""Apply a function to a value."""
return func(value)
print(f"\napply_operation(double, 10) = {apply_operation(double, 10)}")
# -----------------------------------------------------------------------------
# 10. Practical Examples
# -----------------------------------------------------------------------------
print("\n--- Practical Examples ---")
# Temperature converter
def celsius_to_fahrenheit(celsius):
"""Convert Celsius to Fahrenheit."""
return (celsius * 9/5) + 32
def fahrenheit_to_celsius(fahrenheit):
"""Convert Fahrenheit to Celsius."""
return (fahrenheit - 32) * 5/9
print(f"20°C = {celsius_to_fahrenheit(20):.1f}°F")
print(f"68°F = {fahrenheit_to_celsius(68):.1f}°C")
# Password validator
def is_valid_password(password):
"""
Check if password meets requirements:
- At least 8 characters
- Contains uppercase letter
- Contains lowercase letter
- Contains digit
"""
if len(password) < 8:
return False, "Too short"
if not any(c.isupper() for c in password):
return False, "No uppercase letter"
if not any(c.islower() for c in password):
return False, "No lowercase letter"
if not any(c.isdigit() for c in password):
return False, "No digit"
return True, "Valid password"
test_passwords = ["short", "alllowercase", "ALLUPPERCASE", "ValidPass123"]
print("\nPassword validation:")
for pwd in test_passwords:
is_valid, message = is_valid_password(pwd)
print(f" '{pwd}': {message}")