Functions in Python- Definition
Functions in Python are blocks of code that perform a specific task, and they can be defined using the def keyword.
Function template
def function_name(input_varibales, ...):
processing
return output_value_or_exppression
output_variable = function_name(output_values, ...)
print(output_variable)
Definition:
- A function in Python is a block of reusable code that performs a specific task.
- It allows you to break down your program into smaller, more manageable pieces, making your code modular and easier to understand.
Function Call:
- To use a function, you call it by its name followed by parentheses
()
.
Function Name:
- Can contain letters (a-z, A-Z), digits (0-9), and underscores (_)
- Must start with a letter or underscore
- Case-sensitive
Parameters
- Can be positional or keyword-based
- Can have default values
- Can be variable-length (using
*args
or**kwargs
)
Function Body
- Indented block of code
- Can contain statements, expressions, and other functions
- Can include a
return
statement to output values - Can include a
pass
statement as a placeholder when no action is needed
Docstring
- Optional string literal that occurs as the first statement in a function
- Used to document the function’s purpose, parameters, and return values
- Triple quotes (
"""
) are commonly used to delimit docstrings
Return Statement
- Used to output values from a function
- Can return multiple values using tuples or lists
- If no
return
statement is present, the function returnsNone
by default
Pass Statement
- Used as a placeholder when no action is needed
- Can be used to define a function with no body
Lambda Functions
- Small, anonymous functions defined with the
lambda
keyword - Can take any number of arguments, but can only have one expression
Default Argument Values
- Can be specified using the
=
operator - Must be specified after non-default arguments
Variable-Length Arguments
- Can be specified using
*args
or**kwargs
*args
collects positional arguments into a tuple**kwargs
collects keyword arguments into a dictionary
def function_name(*args):
# args is a tuple of non-keyword arguments
pass
def greet(*names):
for name in names:
print(f"Hello, {name}!")
greet("John", "Alice", "Bob")
def function_name(**kwargs):
# kwargs is a dictionary of keyword arguments
pass
def greet(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
greet(name="John", age=30, city="New York")
Keyword-Only Arguments
- Can be specified using the
*
operator - Must be specified after non-keyword-only arguments
Python 3.x
def function_name(*, arg1, arg2, ...):
# arg1, arg2, ... are keyword-only arguments
pass
Example:
def greet(*, name, age):
print(f"Hello, {name}! You are {age} years old.")
greet(name="John", age=30)
Combination of *args, **kwargs, and Keyword-Only Arguments
def function_name(arg1, arg2, *args, kwarg1, kwarg2, **kwargs):
pass
Example:
def greet(name, age, *hobbies, city, country, **kwargs):
print(f"Hello, {name}! You are {age} years old.")
print(f"Hobbies: {hobbies}")
print(f"City: {city}, Country: {country}")
print(f"Additional info: {kwargs}")
greet("John", 30, "reading", "hiking", city="New York", country="USA", occupation="Developer")
Type Hints
- Can be used to specify the expected types of arguments and return values
- Do not affect runtime behavior, but can be used by IDEs and static type checkers
Example
def greet(name: str, age: int = 30) -> str:
"""
Returns a personalized greeting message.
Args:
name (str): The person's name.
age (int, optional): The person's age. Defaults to 30.
Returns:
str: The greeting message.
"""
return f"Hello, {name}! You are {age} years old."
# Test the function
print(greet("John")) # Output: Hello, John! You are 30 years old.
print(greet("Jane", 25)) # Output: Hello, Jane! You are 25 years old.
In simple words-
- def : It is a keyword to define a function.
- Function name should preferably be in snake_case.
- Function defintion can consist of input parameters within ().
- Function definition concludes with : and the body of function continues with indent, typically a tab space.
- Function Call: When the function is called, the flow of control jumps to the function definition.
- Execute Function: Perform the tasks defined inside the function.
- If there’s a return statement, the function returns a value to the caller. return keyword returns the computed value in memory which can be accessed via the calling/output variable.
- It the return statement is not present or not executed the function then returns a None value.
- End: End of the function execution, control returns to the caller.
Snake case, also known as underscore_case, is a naming convention where each word in a compound name is separated by an underscore (_
). All letters are lowercase. Here are some examples:
my_function_name
total_sales_amount
is_user_authenticated
Benefits of Snake Case:
- Readability: Snake case improves code readability by clearly separating words, especially for longer names.
- Consistency: Following a consistent naming convention makes code easier to understand and maintain for both you and others who collaborate on the project.
- Python Convention: Snake case is the widely accepted convention for variable and function names in Python. Using it aligns your code with established practices in the Python community.
Examples of Naming with Snake Case:
Here’s a table illustrating how you can convert function names from other conventions to snake_case:
Original Name | Snake Case Name |
---|---|
calculateTotalSales | calculate_total_sales |
isUserLoggedIn | is_user_logged_in |
checkIfStringIsEmpty | check_if_string_is_empty |
Example Imagine a Function as a MonsterMachine
Think of a function as a special machine in your Python code. You give it certain inputs (like ingredients for a recipe), it performs a specific task (like cooking the ingredients), and then it can optionally provide an output (like the delicious meal!).
Steps to Build Your Function MonsterMachine:
- Name Your MonsterMachine: Choose a descriptive name for your function that reflects what it does. Let’s call our function
greet
. - Define the Inputs (if any): These are like the ingredients you feed into your machine. If your function needs information to complete its task, specify variables within parentheses after the function name. For example,
sayhello(name)
. Here,name
is the input variable. These are Function Parameters:- Functions can take zero or more parameters.You can have default values for parameters as well. - Tell Your MonsterMachine What to Do: Use Python code blocks to instruct your function what to accomplish with the inputs (or without them if there are none). Indentation is crucial here!
- Optional Output: If your function needs to return a value, use the
return
statement. This is like the cooked meal your machine produces.
Let’s Code a Greeter Machine!
Here’s how we can create a function called greet
that takes a name as input and prints a greeting:
Python
def sayhello(name):
"""Prints a greeting message to the user."""
print("Hello,", name + "!")
# Now let's use our greeter machine!
sayhello("Alice") # Output: Hello, Alice!
Experimenting with Your Machine
We can call the greet
function multiple times with different names to see it work its magic:
Python
sayhello("Bob") # Output: Hello, Bob!
sayhello("Charlie") # Output: Hello, Charlie!
Challenge: Build a Pizza Order Machine!
Can you create a function called order_pizza
that takes the size (small, medium, large) and the number of toppings (as an integer) as inputs, and then prints the pizza order details?
Here’s a hint:
def order_pizza(size, num_toppings):
# ... your code here ...
# Test your order_pizza function!
order_pizza("medium", 2) # Output: You ordered a medium pizza with 2 toppings.
Parameters & Return Statement


Returning Values with Conditions:-
Magic8Ball Problem in Python
import random
def magic_8_ball_response(number):
if number == 0:
return "It is certain."
elif number == 1:
return "It is decidedly so."
elif number == 2:
return "Without a doubt."
elif number == 3:
return "Yes – definitely."
elif number == 4:
return "You may rely on it."
elif number == 5:
return "As I see it, yes."
elif number == 6:
return "Most likely."
elif number == 7:
return "Outlook good."
elif number == 8:
return "Yes."
elif number == 9:
return "Signs point to yes."
elif number == 10:
return "Reply hazy, try again."
elif number == 11:
return "Ask again later."
elif number == 12:
return "Better not tell you now."
elif number == 13:
return "Cannot predict now."
elif number == 14:
return "Concentrate and ask again."
elif number == 15:
return "Don't count on it."
elif number == 16:
return "My reply is no."
elif number == 17:
return "My sources say no."
elif number == 18:
return "Outlook not so good."
elif number == 19:
return "Very doubtful."
else:
return "Error: Invalid number."
def magic_8_ball():
print("Welcome to the Magic 8 Ball!")
question = input("Ask a yes or no question (or type 'quit' to exit): ")
if question.lower() == 'quit':
print("Goodbye!")
elif question.strip() == "":
print("You didn't ask a question!")
else:
number = random.randint(0, 19)
response = magic_8_ball_response(number)
print("Magic 8 Ball says: " + response)
if __name__ == "__main__":
magic_8_ball()
import random
def magic_8_ball():
answers = [
"It is certain.",
"It is decidedly so.",
"Without a doubt.",
"Yes – definitely.",
"You may rely on it.",
"As I see it, yes.",
"Most likely.",
"Outlook good.",
"Yes.",
"Signs point to yes.",
"Reply hazy, try again.",
"Ask again later.",
"Better not tell you now.",
"Cannot predict now.",
"Concentrate and ask again.",
"Don't count on it.",
"My reply is no.",
"My sources say no.",
"Outlook not so good.",
"Very doubtful."
]
print("Welcome to the Magic 8 Ball!")
question = input("Ask a yes or no question (or type 'quit' to exit): ")
if question.lower() == 'quit':
print("Goodbye!")
elif question.strip() == "":
print("You didn't ask a question!")
else:
response = random.choice(answers)
print("Magic 8 Ball says: " + response)
if __name__ == "__main__":
magic_8_ball()
import random
def magic_8_ball():
answers = [
"It is certain.",
"It is decidedly so.",
"Without a doubt.",
"Yes – definitely.",
"You may rely on it.",
"As I see it, yes.",
"Most likely.",
"Outlook good.",
"Yes.",
"Signs point to yes.",
"Reply hazy, try again.",
"Ask again later.",
"Better not tell you now.",
"Cannot predict now.",
"Concentrate and ask again.",
"Don't count on it.",
"My reply is no.",
"My sources say no.",
"Outlook not so good.",
"Very doubtful."
]
print("Welcome to the Magic 8 Ball!")
while True:
question = input("Ask a yes or no question (or type 'quit' to exit): ")
if question.lower() == 'quit':
print("Goodbye!")
break
response = random.choice(answers)
print("Magic 8 Ball says: " + response)
if __name__ == "__main__":
magic_8_ball()
Scope in Function @python
In Python, the scope of a variable refers to the region of the program where that variable is recognized. Variables can be defined in different parts of a program, and their scope determines where they can be accessed. There are four types of variable scopes in Python:
- Local Scope
- Enclosing (or nonlocal) Scope
- Global Scope
- Built-in Scope
1. Local Scope
Variables defined within a function have a local scope and are only accessible within that function.
def my_function():
local_var = 10 # Local variable
print(local_var)
my_function() # Output: 10
print(local_var) # NameError: name 'local_var' is not defined
2. Enclosing (or nonlocal) Scope
This scope is relevant for nested functions. The enclosing scope refers to the scope of the outer function in which a nested function is defined.
def outer_function():
enclosing_var = 20
def inner_function():
print(enclosing_var) # Accesses enclosing variable
inner_function()
outer_function() # Output: 20
To modify an enclosing variable from within a nested function, you can use the nonlocal
keyword.
def outer_function():
enclosing_var = 20
def inner_function():
nonlocal enclosing_var
enclosing_var = 30
print(enclosing_var)
inner_function() # Output: 30
print(enclosing_var) # Output: 30
outer_function()
3. Global Scope
Variables defined at the top level of a script or module are in the global scope. They are accessible from any part of the code, including within functions (unless shadowed by a local variable).
global_var = 40 # Global variable
def my_function():
print(global_var) # Accesses global variable
my_function() # Output: 40
print(global_var) # Output: 40
To modify a global variable within a function, you can use the global
keyword.
global_var = 50
def my_function():
global global_var
global_var = 60
print(global_var)
my_function() # Output: 60
print(global_var) # Output: 60
4. Built-in Scope
This is the scope for built-in names like len
, print
, etc. These are always available in any part of the code.
print(len([1, 2, 3])) # len is a built-in function
Scope Resolution (LEGB Rule)
Python resolves variable names using the LEGB rule, which stands for Local, Enclosing, Global, Built-in.
- Local: Names defined within a function.
- Enclosing: Names defined in the enclosing function(s) for nested functions.
- Global: Names defined at the top level of a script or module.
- Built-in: Names preassigned in the built-in names module.
Example of LEGB Rule
# Built-in scope
def min():
return "This is the built-in min function."
def outer_function():
# Global scope
global_var = "I am in the global scope."
# Enclosing scope
enclosing_var = "I am in the enclosing scope."
def inner_function():
# Local scope
local_var = "I am in the local scope."
print(local_var) # Accessing local variable
print(enclosing_var) # Accessing enclosing variable
print(global_var) # Accessing global variable
print(min()) # Accessing built-in function
inner_function()
outer_function()
Key Points to Remember
- Local variables are only accessible within the function they are defined in.
- Enclosing variables are accessible within nested functions and can be modified using the
nonlocal
keyword. - Global variables are accessible throughout the module and can be modified using the
global
keyword. - Built-in names are always available and can be overridden (though not recommended).
What happen behind the scene in Python when a function gets called?
When a function gets called in Python, a series of steps occur behind the scenes. These steps manage the execution of the function, handle its local environment, and ensure the proper flow of control. Here’s a detailed breakdown of what happens:
1. Function Call
When a function is called, Python interprets the call and prepares to execute the function’s code.
def my_function():
print("Hello, world!")
my_function() # Function call
2. Stack Frame Creation
A new stack frame (also known as an activation record) is created for the function call. This stack frame contains:
- Local variables and arguments: Storage for the function’s local variables and parameters.
- Return address: Information on where to return after the function execution completes.
- Instruction pointer: Keeps track of the current position in the function’s code.
3. Argument Passing
The arguments provided to the function call are evaluated and passed to the function. These arguments are then stored in the new stack frame.
def add(a, b):
return a + b
result = add(2, 3) # Arguments 2 and 3 are evaluated and passed to `a` and `b`
4. Local Scope and Environment Setup
The function’s local scope and environment are set up. This includes:
- Initializing local variables: Variables declared inside the function.
- Binding arguments to parameters: The passed arguments are bound to the function’s parameters.
- Setting up the local namespace: A dictionary that holds the function’s local variables.
5. Code Execution
The function’s code is executed line by line. The instruction pointer within the stack frame keeps track of the current line being executed.
def my_function():
x = 10 # Local variable initialization
y = 20 # Local variable initialization
return x + y # Code execution
result = my_function() # Function execution
6. Function Return
When the function execution completes, it returns a value (if any). The return value is passed back to the calling location.
def add(a, b):
return a + b
result = add(2, 3) # `result` receives the value 5
7. Stack Frame Cleanup
After the function returns, its stack frame is destroyed, and the local variables and parameters go out of scope. The return address in the calling function is used to continue execution from where the function was called.
8. Back to Caller
Control returns to the point in the code where the function was called. The function’s return value can be used in subsequent operations.
def multiply(a, b):
return a * b
result = multiply(4, 5) # Control returns here with the result 20
print(result) # Output: 20
Example Walkthrough
Let’s go through a more detailed example:
def greet(name):
message = f"Hello, {name}!"
return message
print(greet("Alice"))
- Function Call:
greet("Alice")
is called. - Stack Frame Creation: A new stack frame is created for
greet
. - Argument Passing: The argument
"Alice"
is passed and bound to the parametername
. - Local Scope and Environment Setup: The local variable
message
is initialized. - Code Execution:
message = f"Hello, {name}!"
is executed, resulting inmessage
being"Hello, Alice!"
.return message
is executed, returning"Hello, Alice!"
.
- Function Return: The function returns the string
"Hello, Alice!"
. - Stack Frame Cleanup: The stack frame for
greet
is destroyed. - Back to Caller: Control returns to the
print
statement, which outputs"Hello, Alice!"
.
Behind the Scenes
- Namespace Management: Each function call has its own local namespace, separate from the global namespace.
- Garbage Collection: Local variables are cleaned up once they go out of scope, freeing memory.
- Call Stack: The call stack manages function calls, with each call creating a new stack frame.
Leave a Reply