Introduction
We have been discussing Python and its versatility. Now is the time to understand another functionality of this powerful programming language: it enhances code efficiency and readability. Maintaining the modularity of your code logic while working on a production-level program is important.
Python Function definition allows the developers to achieve this by encapsulating the codes. On the other hand, lambda functions provide a compact way to define simple functions in Python.
In this guide, we will explore the syntaxes, usages, and best practices for both types of Python functions to build a solid foundation for leveraging these tools in your Python projects in the industry. Whether you want to break complex tasks into simpler functions or utilize lambda functions for concise operations, these methods will help you write efficient code.
To refresh your Python basic to advance, go through these –
- Comprehensive Guide to Advanced Python Programming- Link
- Comprehensive Guide to Python Built-in Data Structures – Link
- Fundamentals of Python Programming for Beginners- Link
What is a Function?
A function in Python is a reusable block of code that performs a specific task depending on the program’s logic. They can take inputs (known as parameters or arguments), perform certain operations, and return outputs.
Functions are really helpful in organizing code, making it more readable, maintainable, and efficient in production.
Python Function uses two Most Important Principles:
- Abstraction: This principle makes the function hide the details of the complex implementation while showing only the essential features (i.e., whatever is returned as output).
- Decomposition: This principle involves breaking down a big task into smaller, more manageable function blocks to avoid redundancy and facilitate easier debugging.
Syntax:
The function syntax involves two things:
In this part, you’ll write a logic, including a docstring, using the `def` keyword.
def function_name(paramters):
"""
doc-string
"""
function logic (body)
return output
The above function does not return any output on its own. To print the output on the screen, you need to call the function using this syntax.
function_name(arguments)
Let’s explore an example of how to create a function.
Creating Function
Now, let’s create our first function, including a docstring.
# Function body
def is_even(num:int):
"""
Check if a number is even or odd.
Parameters:
num (int): The number to check.
Returns:
str: "even" for the even number and, "odd" if the number is odd.
"""
# Function logic
if type(num) == int:
if num % 2 == 0:
return "even"
else:
return "odd"
else:
return "Function needs an integer aruguement"
# Calling function
for i in range(1,11):
print(i, "is", is_even(i))
Output
1 is odd2 is even
3 is odd
4 is even
5 is odd
6 is even
7 is odd
8 is even
9 is odd
10 is even
How do you run documentation?
You can use `.__doc__` to access the docstring of your function (or any built-in function, which we have discussed here).
print(is_even.__doc__)
Output
Check if a number is even or odd.Parameters:
num (int): The number to check.
Returns:
str: "even" for the even number and, "odd" if the number is odd.
To Note:
Programmers often confuse the parameter/s and the argument/s and use them interchangeably while speaking. But let’s understand the difference between them so that you never get into this dilemma.
- Parameter: A parameter is a variable named in the function or method definition (in `class`). It acts as a placeholder for the data the function will use in the future.
- Argument: The actual value is passed to the function or method when it is called to return the output according to the function logic.
Types of Arguments in Python
Due to their versatility, Python functions can accept different types of arguments, providing flexibility in how to call them.
The main types of arguments are:
- Default Arguments
- Positional Arguments
- Keyword Arguments
- Arbitrary Positional Arguments (*args)
- Arbitrary Keyword Arguments (**kwargs)
Let’s understand them one by one:
1. Default Arguments
- Arguments that assume a default value while writing the function, if a value is not provided during the function call.
- Useful for providing optional parameters when user doesn’t enter the value.
def greet(name, message="Hello"):
return f"{message}, {name}!"
print(greet("Nikita"))
print(greet("Nikita", "Hi"))
Outputs
Hello, Nikita!
Hi, Nikita!
2. Positional Arguments
- Arguments passed to a function in a specific order are called positional arguments.
- The order in which the arguments are passed matters, or else it may return the wrong output or error.
def add(a, b):
return a + b
print(add(2, 3))
Output
Outputs: 5
3. Keyword Arguments
- Arguments that are passed to a function using the parameter name as a reference are known as Keyword Arguments.
- The order doesn’t matter herein, as each argument is assigned to the corresponding parameter.
def greet(name, message):
return f"{message}, {name}!"
print(greet(message="Hello", name="Nikita"))
Output
Outputs: Hello, Nikita!
4. Variable-Length Arguments
`*args` and `**kwargs` are special python keywords that are used to pass the variable length of arguments to function.
- Arbitrary Positional Arguments (*args): This allows a function to accept any number of non-keyword positional arguments.
def sum_all(*args):
print(type(args), args)
return sum(args)
print(sum_all(1, 2, 3, 4))
Output
(1, 2, 3, 4)
# 10
- Arbitrary Keyword Arguments (**kwargs): This allows a function to accept any number of keyword arguments.
def print_details(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
print_details(name="Nikita", age=20)
Output
name: Alice
age: 30
Note: Keyword arguments mean that they contain a key-value pair, like a Python dictionary.
Point to remember
The order of the arguments matters while writing a function to get the proper output:
def function_name(parameter_name, *args, **kwargs):
"""
Logic
"""
Types of Functions in Python
There are several types of functions Python offers the developers, such as:
Function Type | Description | Example |
---|---|---|
Built-in Functions | Predefined functions available in Python. | print(), len(), type() |
User-Defined Functions | Functions created by the user to perform specific tasks. | def greet(name): |
Lambda Functions | Small, anonymous functions with a single expression. | lambda x, y: x + y |
Recursive Functions | Functions that call themselves to solve a problem. | def factorial(n): |
Higher-Order Functions | Functions that take other functions as arguments or return them. | map(), filter(), reduce() |
Generator Functions | Functions that return a sequence of values one at a time using yield. | def count_up_to(max): |
Functions in Python are the 1st Class Citizen
I know this is a very heavy statement if you’ve never heard it before, but let’s discuss it.
Functions in Python are entities that support all the operations generally available to other objects, such as lists, tuples, etc.
Being first-class citizens means functions in Python can:
- Be assigned to variables.
- Be passed as arguments to other functions.
- Be returned from other functions.
- Be stored in data structures.
This flexibility allows for powerful and dynamic programming.
type() and id() of Function
By now, you may be excited to know about the function’s type() and id(). So, let’s code it to understand better:
def sum(num1, num2):
return num1 + num2
print(type(sum))
print(id(sum))
Output
134474514428928
Like other objects, this function also has a class of functions and an ID address where it is stored in memory.
Reassign Function to the Variable
You can also assign a function to a variable, allowing you to call the function using that variable.
x = sum
print(id(x))
x(3,9)
Output
13447451442892812
Note: x will have the same address as sum.
Functions Can Also Be Stored in the Data Structures
You can also store functions in data structures like lists, dictionaries, etc., enabling dynamic function dispatch.
l1 = [sum, print, type]
l1[0](2,3)
# Calling function inside of a list
Output
5
Functions are Immutable data types
Let’s store a function `sum` in a set to prove this. As set will never allow mutable datatypes.
s = {sum}
s
Output
{}
Since we got an output, this confirms that the set is the immutable data types.
Functions Can Also Be Passed as Arguments to Other Functions
You can also pass functions as arguments to other functions, enabling higher-order functions and callbacks.
def shout(text):
return text.upper()
def whisper(text):
return text.lower()
def greet(func, name):
return func(f"Hello, {name}!")
print(greet(shout, "Nikita")) # Outputs: HELLO, NIKITA!
print(greet(whisper, "Nikita")) # Outputs: hello, nikita
Output
HELLO, NIKITA!
hello, nikita
We will cover higher-order functions in detail later in this article. So, stay tuned until the end!
Functions Can Also Be Returned from Other Functions
A function can also return other functions, allowing the creation of multiple functions or decorators.
def create_multiplier(n):
def multiplier(x):
return x * n
return multiplier
double = create_multiplier(2)
print(double(5)) # Outputs: 10
triple = create_multiplier(3)
print(triple(5)) # Outputs: 15
Outputs
10
15
Advantages of using Functions
Python functions offer 3 major advantages, such as
- Code Modularity: Functions allow you to encapsulate the logic within named blocks, breaking down complex problems into smaller, more organized pieces.
- Code Readability: Functions make code much cleaner and easier for others (or yourself) to understand while reviewing and debugging it in the future.
- Code Reusability: Once the logic is created, it can be called multiple times in a program, reducing code redundancy.
Also read: What are Functions in Python and How to Create Them?
What is a Lambda Function?
A lambda function, also called an inline function is a small anonymous function. It can take any number of arguments, but can only have one-line expression. These functions are particularly useful for a short period.
Syntax:
Let’s check some examples:
1. Lambda Function with one variable
# square a value
func = lambda x : x**2
func(5)
Output
25
2. Lambda Function with two variables
# Subtracting a value
func = lambda x=0, y=0: x-y
func(5)
Output
5
3. Lambda Function with `if-else` statement
# Odd or Even
func = lambda x : "even" if x%2==0 else "odd"
func(1418236418)
Output
'even'
Lambda functions vs. Normal functions
Feature | Lambda Function | Normal Function |
---|---|---|
Definition Syntax | Defined using the lambda keyword | Defined using the def keyword |
Syntax Example | lambda x, y: x + y | def add(x, y):\n return x + y |
Function Name | Anonymous (no name) | Named function |
Use Case | Short, simple functions | Complex functions |
Return Statement | Implicit return (single expression) | Explicit return |
Readability | Less readable for complex logic | More readable |
Scoping | Limited to a single expression | Can contain multiple statements |
Decorators | Cannot be decorated | Can be decorated |
Docstrings | Cannot contain docstrings | Can contain docstrings |
Code Reusability | Typically used for short, throwaway functions | Reusable and maintainable code blocks |
Why use the Lambda Function?
Lambda functions do not exist independently. The best approach to using them is with higher-order functions (HOF) like map, filter, and reduce.
While these functions have a limited scope compared to regular functions, they can offer a succinct way to streamline your code, especially in sorting operations.
Also read: 15 Python Built-in Functions which You Should Know while learning Data Science
What are Higher Order Functions(HOF) in Python?
A higher-order function, commonly known as an HOF, can accept other functions as arguments, return functions, or both.
For instance, this is how you can use a HOF:
# HOF
def transform(lambda_func, list_of_elements):
output = []
for i in L:
output.append(f(i))
print(output)
L = [1, 2, 3, 4, 5]
# Calling function
transform(lambda x: x**2, L)
Output
[1, 4, 9, 16, 25]
The main function in this code snippet is to take a lambda function and a list of elements.
Note: As per the problem statement, you can apply any specific logic using this lambda function.
Now, let’s dive deep into the Types of HOFs.
What are 3 HOF in Python?
Here are 3 HOF in Python:
1. map()
It applies a given function to each item of an iterable (e.g., list, dictionary, tuple) and returns a list of the results.
For instance,
# Fetch names from a list of dict
people = [
{"name": "Alice", "age": 25},
{"name": "Bob", "age": 30},
{"name": "Charlie", "age": 35},
{"name": "David", "age": 40}
]
list(map(lambda person: person["name"], people))
Output
['Alice', 'Bob', 'Charlie', 'David']
2. filter()
It creates a list of elements for which a given function returns `True`, similar to any filter operation in different programming languages.
For instance,
# filter: fetch names of people older than 30
filtered_names = filter(lambda person: person["age"] > 30, people)
filtered_names_list = map(lambda person: person["name"], filtered_names)
print(list(filtered_names_list))
Output
['Charlie', 'David']
3. reduce()
It applies a function cumulatively to the items of an iterable, reducing it to a single value.
For instance,
# reduce: concatenate all names into a single string
concatenated_names = reduce(lambda x, y: x + ", " + y, map(lambda person: person["name"], people))
print(concatenated_names)
Output
Alice, Bob, Charlie, David
Note: All of these functions expect a lambda function and an iterable.
Conclusion
To conclude this article on Python Functions Definition and Lambda Functions, I would say that if you aim to write robust and scalable code, it is really important to master both of these functionalities to work in real-life industries.
Additionally, this practice helps in writing cleaner code and enhances collaboration throughout the team, as other programmers can easily understand and use the predefined functions to reduce redundancy.
Frequently Asked Questions
Ans. Function definitions, often referred to as normal functions in Python, allow programmers to encapsulate code into reusable blocks to promote modularity, enhance readability, and make it easier to debug.
Ans. Lambda functions, often referred to as anonymous or inline functions, provide a compact way to define simple functions as needed for a short period, such as in sorting operations or within higher-order functions like map(), filter(), and reduce().
Ans. Here’s the difference:
`map()`: Applies a given function to each item of an iterable and returns a list of the results.
`filter()`: creates a list of elements for which a given function returns `True`.
`reduce()`: Applies a function cumulatively to the items of an iterable, reducing it to a single value.