All You Need to know About Functions in Python

Rina Mondal
7 min readApr 23, 2024

--

Photo by Michael Dziedzic on Unsplash

Functions are used to implement a piece of code that is required to be executed multiple times at different locations in the code. Functions allow you to break down your code into smaller, manageable pieces, which makes it easier to read, write, and maintain your code.

In this blog, I have described about:

  1. Definition of a Function
  2. Syntax of a Function
  3. Parameters vs Arguments and Types of Arguments
  4. 9 Characteristics of a Function:
  5. *args and **kwargs
  6. Scope (Local, Global, Variable Shadowing, Non-Local Keyword)

Here’s an example of a simple function in Python:

def greet(name):
"""Prints a greeting message."""
print("Hello, " + name + "!")

# Call the function
greet("Alice")

# Output:
Hello, Alice!

Syntax of a function:

1. def keyword: This keyword is used to define a function in Python.
2. function_name: This is the identifier for the function. It should follow the same rules as variable names. Choose a descriptive name that indicates what the function does.
3. Parameters (optional): Inside the parentheses (), you can specify parameters that the function takes as input.
4. Colon : The colon indicates the beginning of the function body.
5. Docstring (optional): Immediately after the function definition line, you can include a docstring - a string literal enclosed in triple quotes . The docstring serves as documentation for the function, explaining what it does, what parameters it takes, and what it returns. Docstrings are optional but recommended for documenting your code.
6. Body of the function: This is the block of code that performs the desired task of the function. It can include any valid Python statements, expressions, and other function calls.
7. return statement (optional): Inside the function body, you can use the `return` statement to specify the value that the function should return when it is called. If the `return` statement is omitted, the function will return `None` by default. Note that the `return` statement is optional; not all functions need to return a value.

Parameters can also be added to a function:

def function_name(parameter1, parameter2, …):
"""
Docstring: Optional documentation explaining what the function does.
"""
# Body of the function
# Code to perform the desired task
# It may include statements, expressions, and other function calls
# Optional: return statement to return a value from the function
return value

In the above example, greet is a function that takes one parameter name and prints a greeting message. When the function is called with ”Alice” as the argument, it prints ”Hello, Alice!”.

Write a function to add two numbers :

def addition(x, y):
'''This function is to add two numbers'''
return x + y
a=addition(2,3)
print(a)

#Docstring
print(print.__doc__)

Parameters vs Arguments:

Parameter: When you define a function, you specify parameters within the parentheses of the function definition. Parameters are placeholders for the values that the function expects to receive when it is called.

def greet(name):  # 'name' is a parameter
print("Hello, " + name + "!")

Arguments: When you call a function, you provide actual values, known as arguments, to match the parameters defined in the function’s definition. Arguments are the actual values that are passed to the function during its invocation.

greet("Alice")  # "Alice" is an argument

Though the terms are often used interchangeably. Refer to the below example:

def function_name(parameters):
'''Write about the program'''
perform some operations
return

a= function_name(arguments)

Types of Arguments:

  1. Default Arguments: Default arguments, also known as default parameters, are parameters in a function definition that have predefined values.
#Default Arguments
def add(x=1, y=1):
'''This function is to add two numbers'''
return x + y
a=add(2)
print(a)

2. Positional Arguments: When you call a function and provide values for its parameters, those values are assigned to the parameters based on their positions in the function’s parameter list. In other words, the order in which you provide the arguments determines which parameter they correspond to.

#Positonal Arguments
def add(x, y, z):
'''This function is to add two numbers'''
return x + y +z
a=add(2, 3, 5)
print(a)

3. Keyword Arguments: Keyword arguments, also known as named arguments, are a type of argument used in function calls where each argument is preceded by a parameter name and an equals sign (=). This allows you to specify arguments in any order, regardless of the order in which they are defined in the function's parameter list.

#Keyword Arguments
def add(x, y,z):
'''This function is to add two numbers'''
return x + y+z
a=add(y=3,z=5, x=2)
print(a)

Write a program to create a calculator:

def addition(x, y):
return x + y

def subtract(x, y):
return x - y

def multiply(x, y):
return x * y

def divide(x, y):
if y == 0:
return "Error! Division by zero."
else:
return x / y

print("Select operation:")
print("1. Add")
print("2. Subtract")
print("3. Multiply")
print("4. Divide")

while True:
choice = input("Enter choice (1/2/3/4): ")

if choice in ('1', '2', '3', '4'):
num1 = float(input("Enter first number: "))
num2 = float(input("Enter second number: "))

if choice == '1':
print("Result:", add(num1, num2))
elif choice == '2':
print("Result:", subtract(num1, num2))
elif choice == '3':
print("Result:", multiply(num1, num2))
elif choice == '4':
print("Result:", divide(num1, num2))
break
else:
print("Invalid input")
break

Characteristics of Function:

  1. Non Default Argument follows Default Argument: In the below example, the first argument is default and the next argument is non-default. So, it will give an error.
def full_name(first= 'Mike', sur):
first_name=first.capitalize()
sur_name=sur.capitalize()
return first_name +' '+sur_name

name= full_name(first='John', sur='Fernandes')
print(name)

#This code will result in SyntaxError: non-default argument follows default argument

#The correct code will be
def full_name(sur, first='Mike'):
first_name = first.capitalize()
sur_name = sur.capitalize()
return first_name + ' ' + sur_name

name = full_name(sur='Fernandes', first='John')
print(name)

2. Rename a function:

#Assign
def addition(x, y):
return x + y
s=add
print(s)
type(s)
a=s(2,3)
print(a)

3. Delete a Function:

del addition
a=s(2,3)
print(a) #It will result in an error as the function is deleted.

4. Function as an input to another function:

#Function as an input to another function
def addition(a, b):
return a + b

def multiply(a, b):
return a * b

def divide (a,b):
return a/b

def apply_operation(func, x, y):
return func(x, y)

result1 = apply_operation(divide, 6, 4)
print(result1)

5. A function can return another function:

#Returning a function
def outer_function(x):
def inner_function(y):
return x + y
return inner_function

add_5 = outer_function(5)
result = add_5(3)
print(result)
#I have explained this: https://youtu.be/Ss5FPeCLfEk

6. Function without a return statement:

def do_something():
print("This function doesn't return anything.")

result = do_something()
print(result)

7. Nested Function: One function inside another function

#Nested function
def outer_function():
print("Hello, this is the outer function!")
def inner_function():
print("Hello, i m inside")
inner_function()

outer_function()

8. Lambda function/ Anonymous Function:

#Lambda Function
add_numbers = lambda x, y: x + y
result = add_numbers(3, 5)
print(result)
even=lambda x: x%2==0
result=even(4)
print(result)

9. A function returning a lambda function

def create_adder(n):
return lambda x: x + n

add_5 = create_adder(5)
result = add_5(7)
print(result)

#Explanation: https://www.youtube.com/watch?v=Ss5FPeCLfEk

*args and **kwargs:

(Explained:https://www.youtube.com/watch?v=Ss5FPeCLfEk)

*args and **kwargs are special syntax in Python that allow functions to accept an arbitrary number of positional arguments and keyword arguments, respectively. They're useful when you want to define functions with flexible argument lists.

*args: (Arbitrary Positional Arguments):

  • *args is used to pass a variable number of positional arguments to a function.
  • The *args parameter is treated as a tuple inside the function, containing all the positional arguments passed to the function.
  • It allows you to call a function with any number of positional argument.
#*args and **kwargs
def sum_numbers(*coco):
total = 0
for num in coco:
total += num
return total

result = sum_numbers(1, 2, 3, 4, 5,6,7)
print(result)

**kwargs (Arbitrary Keyword Arguments):

  • **kwargs is used to pass a variable number of keyword arguments to a function.
  • The **kwargs parameter is treated as a dictionary inside the function, containing all the keyword arguments passed to the function.
  • It allows you to call a function with any number of keyword arguments.
def my_function(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")

# Call the function with different numbers of keyword arguments
my_function(name='Alice', age=30)
my_function(city='New York', country='USA', population=8_623_000)

Combining *args and **kwargs in a function signature allows it to accept any combination of positional and keyword arguments.

This can be particularly useful when designing flexible and reusable functions.

Scope:

Local Variable: A local variable in Python is a variable declared within the scope of a function or a block. It can only be accessed and used within that specific function or block.

#Local variable
def my_function():
b = 20
print(b)

my_function()

Global Variable: A global variable is declared outside of any function or block and is accessible throughout the entire program, including within functions and blocks. Global variables have global scope, meaning they can be accessed from any part of the program, including inside functions and blocks.

#Global variable
a = 10

def my_function():
print(a)

my_function()

def my_function1():
print(a)

my_function1()

Variable Shadowing:
Variable shadowing occurs when a variable declared in a local scope has the same name as a variable in an outer scope, thus hiding the variable from the outer scope within that local scope. This can lead to unexpected behavior and bugs if not handled properly.

#variable shadowing
a = 10

def shadow_function():
a = 100
print(a)

shadow_function()
print(a)

#Output:
100
10

Global Keyword: The global keyword is used to declare that a variable inside a function belongs to the global scope, meaning it should be treated as a global variable. This allows you to modify the value of a global variable from within a function.

#global keyword
a = 10

def shadow_function():
global a
a =a+1
print(a)

shadow_function()

Non-Local Keyword: the non local keyword is used to declare that a variable inside a nested function (i.e., a function defined within another function) belongs to the outer (non-global) scope.

#nonlocal keyword
def outer_function():
count = 0
def inner_function():
nonlocal count
count += 1
return count
return inner_function

counter = outer_function()
print(counter())
print(counter())
#Output-
1
2

Hence, we have studied every concept related to Function in Python :)

Give it :👏👏👏👏:
If you found this guide helpful , why not show some love? Give it a Clap 👏, and if you have questions or topics you’d like to explore further, drop a comment 💬 below 👇

Free Interview Series on Python: https://www.youtube.com/playlist?list=PL0L9B1Rgyi01woOuzF8yr021K5Bej8-D4

--

--

Rina Mondal

I have an 8 years of experience and I always enjoyed writing articles. If you appreciate my hard work, please follow me, then only I can continue my passion.