Unit 2: Control Flow and Functions

2.1 Conditional Statements

Conditional statements allow a program to make decisions and execute different code blocks based on whether certain conditions are true or false. Python provides three main conditional statements: if, elif, and else.

2.1.1 The if Statement

The if statement is the most basic form of conditional statement. It executes a block of code only if the specified condition evaluates to True.

Syntax:

if condition:
    # Code block to execute if condition is True
    statement(s)

Example:

# Simple if statement
age = 18
if age >= 18:
    print("You are an adult")
    print("You can vote!")

# Output: 
# You are an adult
# You can vote!

Important Points:

  • The condition must evaluate to a Boolean value (True or False)
  • The colon : at the end of the if statement is mandatory
  • Indentation (typically 4 spaces) is crucial in Python - it defines the code block
  • If the condition is False, the code block is skipped entirely

2.1.2 The if-else Statement

The if-else statement provides an alternative block of code to execute when the condition is False.

Syntax:

if condition:
    # Code block if condition is True
    statement(s)
else:
    # Code block if condition is False
    statement(s)

Example:

# Check if a number is positive or negative
number = -5

if number >= 0:
    print("The number is positive or zero")
else:
    print("The number is negative")

# Output: The number is negative

Another Example - Temperature Check:

temperature = 25

if temperature > 30:
    print("It's hot outside! Stay hydrated.")
else:
    print("The weather is pleasant.")

# Output: The weather is pleasant.

2.1.3 The if-elif-else Statement

When you need to check multiple conditions, use the elif (else if) statement. Python checks each condition in order and executes the first block where the condition is True.

Syntax:

if condition1:
    # Code block if condition1 is True
    statement(s)
elif condition2:
    # Code block if condition2 is True
    statement(s)
elif condition3:
    # Code block if condition3 is True
    statement(s)
else:
    # Code block if all conditions are False
    statement(s)

Example - Grade Calculator:

score = 75

if score >= 90:
    grade = "A"
    print("Excellent!")
elif score >= 80:
    grade = "B"
    print("Very Good!")
elif score >= 70:
    grade = "C"
    print("Good!")
elif score >= 60:
    grade = "D"
    print("Satisfactory")
else:
    grade = "F"
    print("Need Improvement")

print(f"Your grade is: {grade}")

# Output:
# Good!
# Your grade is: C

Example - Day of Week:

day = 3

if day == 1:
    print("Monday")
elif day == 2:
    print("Tuesday")
elif day == 3:
    print("Wednesday")
elif day == 4:
    print("Thursday")
elif day == 5:
    print("Friday")
elif day == 6:
    print("Saturday")
elif day == 7:
    print("Sunday")
else:
    print("Invalid day number")

# Output: Wednesday

2.1.4 Nested if Statements

You can place an if statement inside another if statement. This is called nesting.

Example - Loan Eligibility:

age = 25
income = 50000
credit_score = 750

if age >= 18:
    print("Age requirement met")
    if income >= 30000:
        print("Income requirement met")
        if credit_score >= 700:
            print("Congratulations! You qualify for the loan.")
        else:
            print("Sorry, your credit score is too low.")
    else:
        print("Sorry, your income is insufficient.")
else:
    print("Sorry, you must be at least 18 years old.")

# Output:
# Age requirement met
# Income requirement met
# Congratulations! You qualify for the loan.

2.1.5 Conditional Expressions (Ternary Operator)

Python supports a shorthand way to write simple if-else statements in a single line.

Syntax:

value_if_true if condition else value_if_false

Example:

# Traditional if-else
age = 20
if age >= 18:
    status = "Adult"
else:
    status = "Minor"

# Using ternary operator (same result)
status = "Adult" if age >= 18 else "Minor"
print(status)  # Output: Adult

# Finding maximum of two numbers
a, b = 10, 20
maximum = a if a > b else b
print(f"Maximum: {maximum}")  # Output: Maximum: 20

2.1.6 Logical Operators in Conditions

You can combine multiple conditions using logical operators: and, or, and not.

# Using 'and' - Both conditions must be True
age = 25
has_license = True

if age >= 18 and has_license:
    print("You can drive")

# Using 'or' - At least one condition must be True
is_weekend = True
is_holiday = False

if is_weekend or is_holiday:
    print("You can relax today!")

# Using 'not' - Inverts the condition
is_raining = False

if not is_raining:
    print("You can go outside without an umbrella")

# Combining multiple operators
temperature = 25
is_sunny = True
is_weekend = True

if (temperature > 20 and is_sunny) or is_weekend:
    print("Great day for outdoor activities!")

2.1.7 Comparison Operators

Operator Description Example Result
==Equal to5 == 5True
!=Not equal to5 != 3True
>Greater than5 > 3True
<Less than5 < 3False
>=Greater than or equal5 >= 5True
<=Less than or equal5 <= 3False

2.2 Loops: for and while

Loops are used to execute a block of code repeatedly. Python provides two main types of loops: for loop (used when you know the number of iterations) and while loop (used when you want to loop until a condition becomes False).

2.2.1 The while Loop

The while loop executes a block of code as long as the specified condition is True.

Syntax:

while condition:
    # Code block to execute
    statement(s)
    # Update condition variable (important to avoid infinite loop)

Example - Counting:

# Print numbers 1 to 5
count = 1
while count <= 5:
    print(count)
    count += 1  # Important: increment to avoid infinite loop

# Output:
# 1
# 2
# 3
# 4
# 5

Example - Sum of Numbers:

# Calculate sum of numbers from 1 to 10
total = 0
number = 1

while number <= 10:
    total += number
    number += 1

print(f"Sum of numbers 1 to 10 is: {total}")
# Output: Sum of numbers 1 to 10 is: 55

Example - User Input Validation:

# Keep asking until correct password is entered
password = ""

while password != "python123":
    password = input("Enter password: ")
    if password != "python123":
        print("Incorrect password. Try again.")

print("Access granted! Welcome!")

# The loop continues until the user enters "python123"

Example - Factorial Calculation:

# Calculate factorial of a number
number = 5
factorial = 1
i = 1

while i <= number:
    factorial *= i
    i += 1

print(f"Factorial of {number} is {factorial}")
# Output: Factorial of 5 is 120

while-else Statement

Python's while loop can have an optional else block that executes when the condition becomes False (not when broken).

count = 1

while count <= 3:
    print(f"Count: {count}")
    count += 1
else:
    print("Loop completed successfully!")

# Output:
# Count: 1
# Count: 2
# Count: 3
# Loop completed successfully!

2.2.2 The for Loop

The for loop is used to iterate over a sequence (list, tuple, string, range, etc.) or any iterable object.

Syntax:

for variable in sequence:
    # Code block to execute
    statement(s)

Using range() Function

The range() function generates a sequence of numbers.

# range(stop) - generates 0 to stop-1
for i in range(5):
    print(i, end=" ")
# Output: 0 1 2 3 4

print()  # New line

# range(start, stop) - generates start to stop-1
for i in range(1, 6):
    print(i, end=" ")
# Output: 1 2 3 4 5

print()

# range(start, stop, step) - generates with step increment
for i in range(0, 10, 2):
    print(i, end=" ")
# Output: 0 2 4 6 8

print()

# Counting backwards
for i in range(5, 0, -1):
    print(i, end=" ")
# Output: 5 4 3 2 1

Iterating Over Strings

# Print each character in a string
word = "Python"

for char in word:
    print(char, end=" ")
# Output: P y t h o n

# Count vowels in a string
text = "Hello World"
vowels = "aeiouAEIOU"
vowel_count = 0

for char in text:
    if char in vowels:
        vowel_count += 1

print(f"\nNumber of vowels: {vowel_count}")
# Output: Number of vowels: 3

Iterating Over Lists

# Iterate over a list
fruits = ["apple", "banana", "cherry", "date"]

for fruit in fruits:
    print(f"I like {fruit}")

# Output:
# I like apple
# I like banana
# I like cherry
# I like date

# Calculate sum of list elements
numbers = [10, 20, 30, 40, 50]
total = 0

for num in numbers:
    total += num

print(f"Sum: {total}")  # Output: Sum: 150

Using enumerate() Function

The enumerate() function returns both the index and value of each item.

fruits = ["apple", "banana", "cherry"]

for index, fruit in enumerate(fruits):
    print(f"Index {index}: {fruit}")

# Output:
# Index 0: apple
# Index 1: banana
# Index 2: cherry

# Start index from 1
for index, fruit in enumerate(fruits, start=1):
    print(f"Fruit {index}: {fruit}")

# Output:
# Fruit 1: apple
# Fruit 2: banana
# Fruit 3: cherry

for-else Statement

The else block in a for loop executes when the loop completes normally (without break).

# Search for a number
numbers = [1, 3, 5, 7, 9]
target = 5

for num in numbers:
    if num == target:
        print(f"Found {target}!")
        break
else:
    print(f"{target} not found in the list")

# Output: Found 5!

2.2.1 Loop Control Statements

Loop control statements change the execution from its normal sequence. Python provides three loop control statements: break, continue, and pass.

The break Statement

The break statement terminates the loop immediately and transfers control to the statement following the loop.

# Exit loop when condition is met
for i in range(1, 11):
    if i == 6:
        print("Breaking the loop!")
        break
    print(i)

# Output:
# 1
# 2
# 3
# 4
# 5
# Breaking the loop!

# Search and exit
names = ["Alice", "Bob", "Charlie", "David"]
search_name = "Charlie"

for name in names:
    if name == search_name:
        print(f"Found {search_name}!")
        break
    print(f"Checking {name}...")

# Output:
# Checking Alice...
# Checking Bob...
# Found Charlie!

The continue Statement

The continue statement skips the current iteration and moves to the next iteration of the loop.

# Skip even numbers
for i in range(1, 11):
    if i % 2 == 0:
        continue  # Skip even numbers
    print(i)

# Output: 1 3 5 7 9

# Skip specific items
fruits = ["apple", "banana", "cherry", "date"]

for fruit in fruits:
    if fruit == "banana":
        continue
    print(f"I like {fruit}")

# Output:
# I like apple
# I like cherry
# I like date

The pass Statement

The pass statement is a null operation. It does nothing and is used as a placeholder when a statement is syntactically required.

# Placeholder for future code
for i in range(5):
    if i == 2:
        pass  # TODO: Add special handling for 2
    print(i)

# Output: 0 1 2 3 4

# Empty function placeholder
def future_function():
    pass  # Will implement later

# Empty class placeholder
class MyClass:
    pass  # Will add methods later

# Empty if block
x = 10
if x > 5:
    pass  # Handle this case later
else:
    print("x is 5 or less")

Comparison Table

Statement Description Effect
break Terminates the loop Exits the loop entirely
continue Skips current iteration Continues with next iteration
pass Does nothing Placeholder, execution continues

2.2.2 Nested Loops

A nested loop is a loop inside another loop. The inner loop executes completely for each iteration of the outer loop.

Example - Multiplication Table:

# Print multiplication table for 1 to 5
for i in range(1, 6):
    print(f"Table of {i}:")
    for j in range(1, 11):
        print(f"  {i} x {j} = {i * j}")
    print()  # Empty line between tables

# Sample Output:
# Table of 1:
#   1 x 1 = 1
#   1 x 2 = 2
#   ... and so on

Example - Pattern Printing (Right Triangle):

# Print right triangle pattern
rows = 5

for i in range(1, rows + 1):
    for j in range(i):
        print("*", end=" ")
    print()  # Move to next line

# Output:
# *
# * *
# * * *
# * * * *
# * * * * *

Example - Inverted Triangle:

# Print inverted triangle pattern
rows = 5

for i in range(rows, 0, -1):
    for j in range(i):
        print("*", end=" ")
    print()

# Output:
# * * * * *
# * * * *
# * * *
# * *
# *

Example - Number Pyramid:

# Print number pattern
rows = 5

for i in range(1, rows + 1):
    for j in range(1, i + 1):
        print(j, end=" ")
    print()

# Output:
# 1
# 1 2
# 1 2 3
# 1 2 3 4
# 1 2 3 4 5

Example - Working with 2D Lists:

# Iterate through a 2D list (matrix)
matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

print("Matrix elements:")
for row in matrix:
    for element in row:
        print(element, end=" ")
    print()

# Output:
# 1 2 3
# 4 5 6
# 7 8 9

# Calculate sum of all elements
total = 0
for row in matrix:
    for element in row:
        total += element
print(f"Sum of all elements: {total}")  # Output: 45

Example - Finding Prime Numbers:

# Print prime numbers from 2 to 20
print("Prime numbers from 2 to 20:")

for num in range(2, 21):
    is_prime = True
    for i in range(2, int(num ** 0.5) + 1):
        if num % i == 0:
            is_prime = False
            break
    if is_prime:
        print(num, end=" ")

# Output: 2 3 5 7 11 13 17 19

2.3 Functions in Python

A function is a block of organized, reusable code that performs a specific task. Functions help in breaking down large programs into smaller, manageable pieces, promoting code reusability and modularity.

Why Use Functions?

  • Code Reusability: Write once, use multiple times
  • Modularity: Break complex problems into smaller tasks
  • Readability: Makes code easier to understand
  • Maintainability: Easier to update and debug
  • Abstraction: Hide complex implementation details

Types of Functions in Python

  1. Built-in Functions: Pre-defined in Python (e.g., print(), len(), input())
  2. User-defined Functions: Created by the programmer
  3. Lambda Functions: Anonymous, small functions

2.3.1 Defining Functions

Syntax:

def function_name(parameters):
    """Docstring: describes what the function does"""
    # Function body
    statement(s)
    return value  # Optional

Key Points:

  • def keyword is used to define a function
  • Function name should follow naming conventions (lowercase, underscores)
  • Parameters are optional
  • Colon : marks the end of the function header
  • Docstring (optional but recommended) describes the function
  • return statement is optional; functions return None by default

Example - Simple Function:

# Define a simple function
def greet():
    """Prints a greeting message"""
    print("Hello, Welcome to Python!")

# Call the function
greet()

# Output: Hello, Welcome to Python!

Example - Function with Parameters:

# Function that accepts a parameter
def greet_user(name):
    """Greets a user by name"""
    print(f"Hello, {name}! Welcome to Python!")

# Call with different arguments
greet_user("Alice")
greet_user("Bob")

# Output:
# Hello, Alice! Welcome to Python!
# Hello, Bob! Welcome to Python!

Example - Function with Multiple Parameters:

# Function to add two numbers
def add_numbers(a, b):
    """Returns the sum of two numbers"""
    result = a + b
    return result

# Call the function
sum_result = add_numbers(5, 3)
print(f"Sum: {sum_result}")

# Output: Sum: 8

# Function to calculate area of rectangle
def calculate_area(length, width):
    """Calculates and returns the area of a rectangle"""
    area = length * width
    return area

# Using the function
rect_area = calculate_area(10, 5)
print(f"Area of rectangle: {rect_area} square units")

# Output: Area of rectangle: 50 square units

Example - Function to Check Even/Odd:

def is_even(number):
    """Returns True if number is even, False otherwise"""
    if number % 2 == 0:
        return True
    else:
        return False

# Or more concisely:
def is_even(number):
    """Returns True if number is even, False otherwise"""
    return number % 2 == 0

# Using the function
print(is_even(4))   # Output: True
print(is_even(7))   # Output: False

Example - Function to Find Maximum:

def find_maximum(a, b, c):
    """Returns the maximum of three numbers"""
    if a >= b and a >= c:
        return a
    elif b >= a and b >= c:
        return b
    else:
        return c

# Using the function
max_num = find_maximum(10, 25, 15)
print(f"Maximum number: {max_num}")

# Output: Maximum number: 25

2.3.2 Parameters and Return Values

Types of Parameters

1. Positional Parameters

Arguments are passed in the order they are defined.

def describe_person(name, age, city):
    """Describes a person"""
    print(f"{name} is {age} years old and lives in {city}")

# Call with positional arguments
describe_person("Alice", 25, "Mumbai")

# Output: Alice is 25 years old and lives in Mumbai

2. Keyword Parameters

Arguments are passed with parameter names, allowing any order.

def describe_person(name, age, city):
    """Describes a person"""
    print(f"{name} is {age} years old and lives in {city}")

# Call with keyword arguments (order doesn't matter)
describe_person(city="Delhi", name="Bob", age=30)

# Output: Bob is 30 years old and lives in Delhi

# Mix positional and keyword (positional must come first)
describe_person("Charlie", city="Pune", age=35)

# Output: Charlie is 35 years old and lives in Pune

3. Default Parameters

Parameters can have default values that are used when no argument is provided.

def greet(name, message="Hello"):
    """Greets with a custom or default message"""
    print(f"{message}, {name}!")

# Call with and without default parameter
greet("Alice")              # Uses default message
greet("Bob", "Good Morning")  # Uses custom message

# Output:
# Hello, Alice!
# Good Morning, Bob!

# Another example with multiple defaults
def create_profile(name, age=18, city="Unknown"):
    """Creates a user profile"""
    return {
        "name": name,
        "age": age,
        "city": city
    }

print(create_profile("Alice"))
print(create_profile("Bob", 25))
print(create_profile("Charlie", 30, "Mumbai"))

# Output:
# {'name': 'Alice', 'age': 18, 'city': 'Unknown'}
# {'name': 'Bob', 'age': 25, 'city': 'Unknown'}
# {'name': 'Charlie', 'age': 30, 'city': 'Mumbai'}

4. Variable-length Arguments (*args)

Used when you don't know how many arguments will be passed.

def calculate_sum(*numbers):
    """Returns sum of all numbers passed"""
    total = 0
    for num in numbers:
        total += num
    return total

# Call with different number of arguments
print(calculate_sum(1, 2, 3))           # Output: 6
print(calculate_sum(10, 20, 30, 40))    # Output: 100
print(calculate_sum(5))                 # Output: 5

# Another example
def print_names(*names):
    """Prints all names passed"""
    for name in names:
        print(f"Hello, {name}!")

print_names("Alice", "Bob", "Charlie")

# Output:
# Hello, Alice!
# Hello, Bob!
# Hello, Charlie!

5. Keyword Variable-length Arguments (**kwargs)

Used to pass a variable number of keyword arguments.

def print_info(**info):
    """Prints key-value pairs of information"""
    for key, value in info.items():
        print(f"{key}: {value}")

print_info(name="Alice", age=25, city="Mumbai")

# Output:
# name: Alice
# age: 25
# city: Mumbai

# Combining *args and **kwargs
def display_data(*args, **kwargs):
    """Displays positional and keyword arguments"""
    print("Positional arguments:")
    for arg in args:
        print(f"  {arg}")
    
    print("\nKeyword arguments:")
    for key, value in kwargs.items():
        print(f"  {key} = {value}")

display_data(1, 2, 3, name="Test", status="Active")

# Output:
# Positional arguments:
#   1
#   2
#   3
#
# Keyword arguments:
#   name = Test
#   status = Active

Return Values

Returning a Single Value

def square(number):
    """Returns the square of a number"""
    return number ** 2

result = square(5)
print(f"Square of 5: {result}")  # Output: Square of 5: 25

Returning Multiple Values

Python functions can return multiple values as a tuple.

def calculate_operations(a, b):
    """Returns sum, difference, product, and quotient"""
    add = a + b
    sub = a - b
    mul = a * b
    div = a / b if b != 0 else None
    return add, sub, mul, div

# Unpack return values
sum_val, diff, prod, quot = calculate_operations(10, 5)
print(f"Sum: {sum_val}")       # Output: Sum: 15
print(f"Difference: {diff}")   # Output: Difference: 5
print(f"Product: {prod}")      # Output: Product: 50
print(f"Quotient: {quot}")     # Output: Quotient: 2.0

# Another example
def get_min_max(numbers):
    """Returns minimum and maximum from a list"""
    return min(numbers), max(numbers)

minimum, maximum = get_min_max([5, 2, 8, 1, 9, 3])
print(f"Min: {minimum}, Max: {maximum}")
# Output: Min: 1, Max: 9

Returning a List or Dictionary

# Return a list
def get_even_numbers(limit):
    """Returns a list of even numbers up to limit"""
    evens = []
    for i in range(2, limit + 1, 2):
        evens.append(i)
    return evens

print(get_even_numbers(10))  # Output: [2, 4, 6, 8, 10]

# Return a dictionary
def create_student(name, age, grade):
    """Creates and returns a student dictionary"""
    student = {
        "name": name,
        "age": age,
        "grade": grade
    }
    return student

student1 = create_student("Alice", 20, "A")
print(student1)
# Output: {'name': 'Alice', 'age': 20, 'grade': 'A'}

Functions Without Return Statement

Functions without a return statement return None by default.

def print_message(message):
    """Prints a message (no return value)"""
    print(message)

result = print_message("Hello!")
print(f"Return value: {result}")

# Output:
# Hello!
# Return value: None

2.3.3 Scope and Lifetime of Variables

Scope refers to the region of the program where a variable can be accessed. Lifetime refers to how long a variable exists in memory during program execution.

Types of Variable Scope

1. Local Scope

Variables defined inside a function are local variables. They can only be accessed within that function.

def my_function():
    # Local variable
    x = 10
    print(f"Inside function: x = {x}")

my_function()
# print(x)  # Error! x is not defined outside function

# Output: Inside function: x = 10

2. Global Scope

Variables defined outside all functions are global variables. They can be accessed throughout the program.

# Global variable
message = "Hello, World!"

def greet():
    # Accessing global variable
    print(message)

def farewell():
    print(f"Goodbye! {message}")

greet()
farewell()

# Output:
# Hello, World!
# Goodbye! Hello, World!

3. Global vs Local Variables with Same Name

If a local variable has the same name as a global variable, the local variable takes precedence inside the function.

x = "global x"

def test_scope():
    x = "local x"  # This creates a new local variable
    print(f"Inside function: {x}")

test_scope()
print(f"Outside function: {x}")

# Output:
# Inside function: local x
# Outside function: global x

4. The global Keyword

Use the global keyword to modify a global variable inside a function.

counter = 0  # Global variable

def increment():
    global counter  # Declare we want to use the global variable
    counter += 1
    print(f"Counter inside function: {counter}")

print(f"Initial counter: {counter}")
increment()
increment()
increment()
print(f"Final counter: {counter}")

# Output:
# Initial counter: 0
# Counter inside function: 1
# Counter inside function: 2
# Counter inside function: 3
# Final counter: 3

Note: While the global keyword works, it's generally better to pass values as parameters and return modified values. This makes code more readable and maintainable.

5. Enclosing Scope (Nested Functions)

When functions are nested, the inner function can access variables from the enclosing (outer) function.

def outer_function():
    outer_var = "I'm from outer function"
    
    def inner_function():
        print(outer_var)  # Can access outer_var
    
    inner_function()

outer_function()

# Output: I'm from outer function

6. The nonlocal Keyword

Use nonlocal to modify a variable from the enclosing scope in a nested function.

def outer_function():
    count = 0
    
    def inner_function():
        nonlocal count  # Modify the enclosing variable
        count += 1
        print(f"Count: {count}")
    
    inner_function()
    inner_function()
    inner_function()
    print(f"Final count: {count}")

outer_function()

# Output:
# Count: 1
# Count: 2
# Count: 3
# Final count: 3

Variable Lifetime

Lifetime of Local Variables

Local variables exist only during the function execution. They are created when the function is called and destroyed when the function returns.

def demo_lifetime():
    # 'temp' is created when function is called
    temp = "I exist only during function execution"
    print(temp)
    # 'temp' is destroyed when function ends

demo_lifetime()  # Creates and destroys 'temp'
demo_lifetime()  # Creates a NEW 'temp' and destroys it

# Each call creates a fresh local variable

Lifetime of Global Variables

Global variables exist throughout the program's execution, from when they're created until the program terminates.

app_name = "Python Study Hub"  # Created at program start

def display_app():
    print(f"Application: {app_name}")

display_app()
# app_name continues to exist after function call
print(f"App still exists: {app_name}")

# Output:
# Application: Python Study Hub
# App still exists: Python Study Hub

LEGB Rule

Python searches for variables in this order (LEGB):

Scope Description Example
Local Variables inside the current function Variables defined in the function body
Enclosing Variables in enclosing function (for nested functions) Outer function's local variables
Global Variables at the module level Variables defined at top of file
Built-in Python's built-in names print, len, range, etc.
# LEGB Example
x = "global"  # Global scope

def outer():
    x = "enclosing"  # Enclosing scope
    
    def inner():
        x = "local"  # Local scope
        print(f"Inner: {x}")
    
    inner()
    print(f"Outer: {x}")

outer()
print(f"Global: {x}")

# Output:
# Inner: local
# Outer: enclosing
# Global: global

Best Practices for Variable Scope

  • Minimize global variables: Use parameters and return values instead
  • Use descriptive names: Helps avoid confusion between scopes
  • Keep functions focused: Each function should have a single responsibility
  • Pass data explicitly: Rather than relying on global state
  • Document scope usage: Comment when using global or nonlocal keywords

Example - Good Practice:

# Good practice: Using parameters and return values
def calculate_total(prices, tax_rate):
    """Calculate total with tax"""
    subtotal = sum(prices)
    tax = subtotal * tax_rate
    total = subtotal + tax
    return total

prices = [100, 200, 150]
tax_rate = 0.18

result = calculate_total(prices, tax_rate)
print(f"Total amount: ₹{result}")

# Output: Total amount: ₹531.0

Summary

Conditional Statements

  • if - Execute code when condition is True
  • elif - Check additional conditions
  • else - Execute when all conditions are False
  • Ternary operator: value_if_true if condition else value_if_false

Loops

  • while - Loop while condition is True
  • for - Iterate over sequences
  • break - Exit loop immediately
  • continue - Skip to next iteration
  • pass - Placeholder, does nothing

Functions

  • Define with def function_name(parameters):
  • Parameters: positional, keyword, default, *args, **kwargs
  • Return values with return statement
  • Can return multiple values as tuple

Variable Scope

  • Local: Inside function, accessible only there
  • Global: Outside functions, accessible everywhere
  • LEGB Rule: Local → Enclosing → Global → Built-in
  • global keyword to modify global variables
  • nonlocal keyword for enclosing scope variables