Python : Functions

Some tasks need to be performed multiple times within a program. Rather than rewrite the same code in multiple places, a function may be defined using the def keyword. Function definitions may include parameters, providing data input to the function.

Syntax

def my_function(value):  
    return value + 1
print(my_function(2))print(my_function(3 + 5))

Functions may return a value using the return keyword followed by a value. They can then be called, or invoked, elsewhere in the program. The output from the snippet above would look like this:

39

Note: Function names in Python are written in snake_case.

Return Values

The return keyword is used to return a value from a Python function. The value returned from a function can be assigned to a variable which can then be used in the program.

In the example below, the check_leap_year() function returns a string that indicates if the passed parameter is a leap year or not.

def check_leap_year(year):
  if year % 4 == 0:
    return str(year) + " is a leap year."
  else:
    return str(year) + " is not a leap year."

year_to_check = 2018

returned_value = check_leap_year(year_to_check)

print(returned_value)

The resulting output will look like this:

2018 is not a leap year.

Returning Values With yield

A function can also return values with the yield keyword. Like return, yield suspends the function’s execution and returns the value specified. Unlike return, the yield statement retains the state of the function and will resume where it left off on the next function call (i.e. execution resumes after the last yield statement). This way, the function can produce a number of values over time.

Functions using yield rather than return are known as generator functions. Such a function can be used as an iterator.

The example below will automatically generate successive Fibonacci numbers.

# Function to produce infinite Fibonacci numbers
def fibonacci():
  # Generate first number
  a = 1
  yield a

  # Generate second number
  b = 1
  yield b

  # Infinite loop
  while True:
    # Return sum of a + b
    c = a + b
    yield c
    # Function resumes loop here on next call
    a = b
    b = c

# Iterate through the Fibonacci sequence until a limit is reached
for num in fibonacci():
  if num > 50:
    break
  print(num)

This will output the following:

1
1
2
3
5
8
13
21
34

Higher-Order Functions

In Python, functions are treated as first-class objects. This means that they can be assigned to variables, stored in data structures, and passed to or returned from other functions.

Functions are considered to be “higher-order” values because they can be used as parameters or return values for other functions. One example is the built-in filter() function:

# run this code in your editor to see the output
def is_perfect_square(n):
  return (n ** 0.5).is_integer()

numbers = [3, 4, 37, 9, 7, 32, 25, 81, 79, 100]

perfect_squares = filter(is_perfect_square, numbers)

print(list(perfect_squares))

filter() takes a predicate (a function that returns a boolean value) and an iterable, and returns a new iterable containing all elements of the first one that makes the predicate true.

Anonymous functions

The act of defining a function using the def keyword binds that function to a name. However, some functions can be defined without giving them a name. Such functions are called “anonymous” and are defined using the lambda keyword.

lambda <parameter_list> : <function_body>

The following two definitions are equivalent.

def add(a, b):  return a + b

add = lambda a, b: a + b

The expression to the right of the assignment operator is called a “lambda expression”. The Python interpreter takes this expression and defines a function object which can be bound to an identifier (in this case, add). There is no difference between binding a function to a name using the assignment operator or by using the def keyword.

Parameters are optional when defining an anonymous function. However, a function body must be present, and it must only contain a single return expression.

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

odd_numbers = filter(lambda n : n % 2 == 1, numbers)

print(list(odd_numbers))

# Output: [1, 3, 5, 7, 9]

Anonymous functions can also be evaluated immediately after they are defined, similar to an immediately-invoked function expression (IIFE) in JavaScript.

# run this code in your editor to see the output
print((lambda a, b: a + b)(1986, 33))

Anonymous functions are useful when the function can be written in a single line. Otherwise, if the function is more complex, it is recommended to use the def keyword

Did you find this article valuable?

Support ALAO LAWAL ADECHINA by becoming a sponsor. Any amount is appreciated!