Functions are one of the most fundamental building blocks in Python programming. They allow you to organize your code into reusable, modular pieces that perform specific tasks.
To create a function in Python, use the def keyword followed by the function name and parentheses ().
Syntax:
def function_name(parameters):
# code block
return value
Example:
#Function to greet a user
def greet(name):
return f"Hello, {name}!"
#Calling the function
print(greet("Alice")) # Output: Hello, Alice!
Functions are executed when you "call" them by their name followed by parentheses ().
Example:
#Define the function
def greet(name):
return f"Hello, {name}!"
#Call the function
print(greet("Bob")) # Output: Hello, Bob
Functions can accept data, known as parameters, which are passed to the function when it is called.
Positional Arguments:
def add(a, b):
return a + b
print(add(2, 3)) # Output: 5
Keyword Arguments:
def greet(name, greeting="Hello"):
return f"{greeting}, {name}!"
print(greet(name="Alice", greeting="Hi")) # Output: Hi, Alice!
print(greet(name="Bob")) # Output: Hello, Bob
Python allows functions to accept an arbitrary number of arguments using *args (for positional arguments) and **kwargs (for keyword arguments).
*args:
def add(*numbers):
return sum(numbers)
print(add(1, 2, 3, 4)) # Output: 10
print(add(5, 10)) # Output: 15
**kwargs:
def greet(**info):
return f"Hello, {info['name']}!"
print(greet(name="Alice", age=30)) # Output: Hello, Alice!
Functions can return a result using the return statement.
Example:
def square(number):
return number ** 2
result = square(4)
print(result) # Output: 16
Explanation:
square takes a number, computes its square, and returns the result.Default parameters allow you to define default values for function arguments. If a value is not provided when calling the function, the default value is used.
Syntax:
def function_name(parameter=default_value):
# code block
Example:
def greet(name, greeting="Hello"):
return f"{greeting}, {name}!"
print(greet("Alice")) # Output: Hello, Alice!
print(greet("Alice", "Hi")) # Output: Hi, Alice!
Explanation:
greeting parameter has a default value of "Hello".greeting, it defaults to "Hello".Functions that do not explicitly return a value will return None by default.
Example:
def say_hello():
print("Hello!")
result = say_hello()
print(result) # Output: None
Explanation:
say_hello() only prints a message but does not return any value.Lambda functions are small, anonymous functions defined using the lambda keyword. They are often used for short, simple operations.
Syntax:
lambda arguments: expression
Example:
#A lambda function to calculate the square of a number
square = lambda x: x ** 2
print(square(5)) # Output: 25
#Using lambda in a map function
numbers = [1, 2, 3, 4]
squares = map(lambda x: x ** 2, numbers)
print(list(squares)) # Output: [1, 4, 9, 16]
Functions can be defined inside other functions. These are called nested functions or inner functions.
Example:
def outer_function(outer_value):
def inner_function(inner_value):
return outer_value + inner_value
return inner_function
add_five = outer_function(5)
print(add_five(10)) # Output: 15
Explanation:
inner_function is defined inside outer_function.outer_function returns inner_function, which remembers the value of outer_value.A higher-order function is a function that takes another function as an argument or returns a function as a result.
Examples:
Using a Function as an Argument:
def apply_function(func, value):
return func(value)
print(apply_function(lambda x: x ** 2, 5)) # Output: 25
Returning a Function:
def multiplier(factor):
return lambda x: x * factor
double = multiplier(2)
print(double(5)) # Output: 10
An exception is an error that occurs during the execution of a program. Python provides tools to detect and handle these errors gracefully.
You can handle exceptions using the try-except block.
Syntax:
try:
# Code that may raise an exception
except ExceptionType:
# Code to handle the exception
Example:
try:
x = int(input("Enter a number: "))
print(f"You entered {x}")
except ValueError:
print("Invalid input! Please enter a valid number.")
Explanation:
try block is executed.ValueError occurs (e.g., entering a non-numeric value), the except block is executed.The finally block is used to execute code regardless of whether an exception occurred or not. It is commonly used for cleanup operations, such as closing a file or releasing resources.
Syntax:
try:
# Code that may raise an exception
except ExceptionType:
# Handle the exception
finally:
# Code that always executes
Example:
try:
file = open("data.txt", "r")
content = file.read()
except FileNotFoundError:
print("File not found!")
finally:
print("Closing the file (if open).")
file.close()
Explanation:
finally block ensures the file is closed even if an exception occurs.You can raise exceptions manually using the raise keyword.
Syntax:
raise ExceptionType("Error message")
Example:
def validate_age(age):
if age < 18:
raise ValueError("Age must be 18 or older.")
return "Valid age"
try:
print(validate_age(15))
except ValueError as e:
print(e) # Output: Age must be 18 or older.
You can handle multiple types of exceptions in a single try-except block by specifying a tuple of exception types.
Example:
try:
value = int(input("Enter a number: "))
result = 10 / value
except (ValueError, ZeroDivisionError) as e:
print(f"Error: {e}")
Explanation:
ValueError or ZeroDivisionError occurs, the corresponding error message is printed.To catch all exceptions, use a bare except clause. However, this is generally discouraged as it may hide unexpected issues.
Example:
try:
result = 10 / 0
except Exception as e:
print(f"An error occurred: {e}")
Explanation:
except Exception clause catches any exception and prints the error message.You can define your own exception classes by inheriting from the built-in Exception class.
Example:
class CustomError(Exception):
def __init__(self, message):
self.message = message
def validate_age(age):
if age < 18:
raise CustomError("Age must be 18 or older.")
return "Valid age"
try:
print(validate_age(15))
except CustomError as e:
print(e.message) # Output: Age must be 18 or older.
Explanation:
CustomError is a user-defined exception.raise keyword when the condition is not met.An else block can be added after except. It runs if no exceptions are raised.
Example:
try:
value = int(input("Enter a number: "))
except ValueError:
print("Invalid input!")
else:
print(f"Valid number: {value}")
Explanation:
ValueError occurs, the else block runs.The contextlib.suppress method can be used to suppress specific exceptions.
Example:
from contextlib import suppress
with suppress(FileNotFoundError):
with open("non_existent_file.txt", "r") as file:
content = file.read()
Explanation:
Be Specific:
except clause.try:
x = int(input("Enter a number: "))
except ValueError:
print("Invalid input!")
Avoid Overusing Exceptions:
Clean Up Resources:
finally block or use a context manager (with statement).Provide Meaningful Messages:
In Python, indentation is mandatory. It is not just for readability—it defines code blocks such as function bodies, loops, conditionals, etc.
def function_name():
# This is the function body
print("Hello") # ← Must be indented
def f():
print("Hi") # SyntaxError: expected an indented block
This will cause a SyntaxError because Python expects the function body to be indented consistently, typically using 4 spaces per indentation level.
Questions may include code like the one above and ask whether it will produce an error. If indentation is missing or inconsistent, the answer is likely SyntaxError.
return Implicitly Return NoneIf a function does not include a return statement, it implicitly returns None.
def f():
pass
print(f()) # Output: None
Even though f() does nothing, Python automatically returns None.
print(type(f())) # Output: <class 'NoneType'>
This confirms that the return value is of type NoneType, which is the type of the built-in singleton None.
You may encounter a question asking what a function returns if it has no return statement. Always remember: the default return is None.
Although the PCEP exam does not require you to write complex exception handling, it does test your ability to recognize which types of errors occur in different scenarios.
Here is a quick-reference list of common Python exceptions you should recognize:
| Exception Name | Description | Example |
|---|---|---|
ValueError |
Raised when a function receives a valid type but an invalid value | int("abc") |
TypeError |
Raised when an operation is performed on incompatible types | "2" + 1 |
ZeroDivisionError |
Raised when dividing a number by zero | 10 / 0 |
IndexError |
Raised when accessing an index that’s out of range in a sequence | [1, 2][5] |
KeyError |
Raised when accessing a dictionary with a key that doesn’t exist | {"a":1}["b"] |
print(int("abc")) # ValueError
print("2" + 1) # TypeError
print(10 / 0) # ZeroDivisionError
print([1, 2][5]) # IndexError
print({"a": 1}["b"]) # KeyError
You may be asked:
"Which line of code will raise a TypeError?"
Recognizing each exception type by its trigger condition is critical for answering such questions quickly and accurately.
| Concept | Key Rule or Insight | Why It Matters |
|---|---|---|
| Indentation | Function body must be indented | Python uses indentation to define blocks |
| Default Return | Functions without return return None |
Can affect logic flow and outputs |
NoneType |
Use type() to confirm default return |
Clarifies behavior in exam questions |
| Exception Names | Know 5–6 common errors by name and cause | Used in multiple-choice logic checking |
What is the difference between return and print in a function?
return sends a value back to the caller, while print displays output to the console.
return allows the function result to be stored or used elsewhere, while print only outputs text. A common mistake is using print when a value needs to be reused, resulting in None being assigned. Understanding this distinction is essential for function design.
Demand Score: 82
Exam Relevance Score: 90
Why does my function return None instead of a value?
A function returns None if no return statement is specified.
If a function lacks an explicit return, Python automatically returns None. This often happens when print is used instead of return. Another cause is placing return inside a conditional that is not always executed. Ensuring all execution paths return a value prevents this issue.
Demand Score: 85
Exam Relevance Score: 92
Why is my try-except block not catching an error?
The exception may not match the specified type or occurs outside the try block.
If the error type differs from the except clause, it won’t be caught. Also, code outside the try block is not protected. A common mistake is using overly specific exceptions or incorrect indentation. Using a general Exception handler can help during debugging.
Demand Score: 83
Exam Relevance Score: 91
What is the purpose of Python’s built-in exception hierarchy?
It organizes exceptions into a structured system for more precise error handling.
Python groups exceptions under base classes like Exception, allowing developers to catch broad or specific errors. This hierarchy enables flexible handling strategies. A common mistake is catching overly broad exceptions, which can hide bugs and make debugging difficult.
Demand Score: 78
Exam Relevance Score: 88