13

USER DEFINED FUNCTIONS

by

The Education Machine

[support@theeducationmachine.com]


Functions are one of the building blocks in python which enables user to modularize the code.

As we have seen various python's inbuilt functions till now such as help, print, type, id, etc. which perform specific tasks. NOTE: we have used these functions a lot of times as per our requirement which means functions are set of reusable code.

Now, What if you want to perform similar task multiple times but you do not have a function for it. In such scenarios, user-defined functions comes into rescue.

User-defined function definition starts with 'def' keyword and the same statement should be ended with a colon then the subsequent statements should be indented.


Below we have created a user defined function which is printing a statement.

  def python_class():
      print("This is a python class")
  python_class()

Output:
This is a python class

In this example, we have passed an argument i.e. string. We can pass multiple arguments as well.

  def python_class2(string):
      print(string)
  
  python_class2('This is a python class')

Output:
This is a python class

While calling the function user can enter any string.

  python_class2('Kashish')

Output:
Kashish

Below we have created a user defined function which is printing the output in 3 lines using an escape character "\n".

  def bio(name, age, gender):
      print(f"Name: {name}\nAge: {age}\nGender: {gender}")
  
  bio('Nayan',15,'F')

Output:
Name: Nayan
Age: 15
Gender: F

Check the datatype of age.

  print(age)

reserved_keywords

As we can see in the above example, we entered 3 arguments which are actually known as positional arguments/parameters. Later, we will learn what are keyword arguments.

Let's try to skip the value of any 1 arguuments, during function call.

  bio('Nayan',15)

reserved_keywords

In positional arguments, user has to enter the value in positional way. If name is at 1st position then user has to write the name at 1st place only, followed by other arguments while calling the function. Below is an example of wrong positional arguments.

  bio('F',15,'Nayan'))

Output:
Name: F
Age: 15
Gender: Nayan

To convert the currency using user defined function.

  def currency_converter(usd):
      print(f"USD to INR is: {usd*75}")
  
  currency_converter(10)
  currency_converter(18)

Output:
USD to INR is: 750
USD to INR is: 1350

To reverse the string in user defined function using indexing.

  def reverse(string):
      return string[::-1]
  
  print(reverse("Python"))

Output:
nohtyP

We can also write 'reverse' function call as this:

  temp = reverse('Python Learning')
  print(temp)
  
  print(reverse("Python"))

Output:
gninraeL nohtyP

Now, let us understand the use of return statement:

1.) Return statement helps us to return values as function output.

2.) Without return statement, we cannot store the output into a variable globally(Any variables created inside a function are local to that function only)

Function that prints if a supplied number is even or odd.

  def even_odd(num):
      if num%2 == 0:
          return "EVEN"
      else:
          return "ODD"
  
  print(even_odd(19))
  print(even_odd(12))

Output:
ODD
EVEN

Efficient Method for above code:

  def even_odd2(num):
      if num%2 == 0:
          return "EVEN"
      return "ODD"
  
  print(even_odd2(19))
  print2(even_odd(12))

Output:
ODD
EVEN

To print bigger number in user defined function.

  def bigger(num1,num2):
      if num1 > num2:
          return num1
      return num2
  
  print(bigger(19,12))

Output:
19

Just to verify the above function with different numbers, we are still getting the biggest value.

  big_num = bigger(19,21)
  print(big_num)

Output:
21

To print the biggest or highest value between 3 numbers.

  def biggest(num1,num2,num3):
      if num1 > num2 and num1 > num3:
          return num1
      elif num2 > num3 and num2 > num1:
          return num2
      return num3
  
  print(biggest(11,15,8))
  print(biggest(1,15,80))
  print(biggest(111,15,8))

Output:
15
80
111

Efficient code of same program when you already have a program to check big number out of 2 numbers.
This is also an example of 'Function inside a function'.

  def biggest_better(num1,num2,num3):
      big1 = bigger(num,num2)
      biggest = bigger(big1, num3)
      return biggest
  
  print(biggest(11,15,8))
  print(biggest(1,15,80))
  print(biggest(111,15,8))

Output:
15
80
111

Much Efficient code of same program when you already have a program to check big number out of 2 numbers.

  def biggest_efficient(num1,num2,num3):
      biggest = bigger(bigger(num1,num2),num3)
      return biggest
  
  print(biggest(11,15,8))
  print(biggest(1,15,80))
  print(biggest(111,15,8))

Keyword Arguments

When user wants to pass arguments value irrespective of the position of the argument in function definition, they can pass the value specifically against each or few arguments.

As per above example, syntax would be:
biggest(num3 = 11, num1 = 15, num2 = 8)

  biggest(num3 = 11, num1 = 15, num2 = 8)

Output:
15

Let us see what would happen if we skip return statement.
The output will not return anything or will show none as shown below:

  def biggest_efficient(num1,num2,num3):
      biggest = bigger(bigger(num1,num2),num3)
  
  print(f"The biggest number is: {biggest_efficient(11,15,8)}")

Output:
The biggest number is: None

Default Arguments

In cases where user do no pass any value for one or more arguments, we can assign a default value to those arguments so that function can be executed without any error/s.

We give default value of arguments in the function definition itself.

See the error when we do not pass value for the second argument.

  def multiply_nums(num1, num2):
      return num1 * num2
  
  multiply_nums(10)

reserved_keywords

# Using default argument.
In default arguments, the python will pick the value user entered while defining the function and the user can skip that argument when calling the function.

  def multiply_nums(num1, num2=20):
      return num1 * num2
  
  print(multiply_nums(10))

Output:
200

If user pass value for the argument, default value will be overwritten.

  print(multiply_nums(10,15))

Output:
150

Modularization

While working with any programming language, it is very important to modularize the code.

Modularizing the code means writing functions definition in some python script and then calling their functions in current python script. Modularization helps us to separate the functions for each task to make our main script looks clean and this structure works in an efficient manner.

Import the file from which you want to access a particular function or code and give it a new name. And whenever you want to use that code, enter new name.the name of the function or code you want to use.
Like in below code,the user wants to import the function called "biggest efficient" which stored in file "test modules" and the new name given to it is "tm".

  import test_modules as tm
  tm.biggest_efficient(100,20,30)

Output:
100

Here, the user wants to use another function from that same file, so, the user can call the function as shown below:

  tm.currency_converter(10)

Output:
750

In bigger function, we are passing 2 arguments but in biggest_efficient function, there are 3 arguments.

  def bigger(num1,num2):
      if num1 > num2:
          return num1
      return num2
  
  def biggest_efficient(num1,num2,num3):
      biggest = bigger(bigger(num1,num2),num3)
      return biggest

Output:
The biggest number is: 15

*args

Now, what if the user wants to pass on multiple arguments in one go without defining them in function definition. Also, sometimes developer wants to accept all the value that user provides as input.

Lets suppose, user1 entered 3 arguments and user2 entered 7 arguments. We will see how we can accept values from both the users.

In such scenarios, we can use *args which helps to call multiple arguments.

*args is just a notation, we can use any string value such as *test, *kashish, etc..

NOTE: Just like tuples or lists, *args is also an iterable at which we can iterate the loop.

  def addition(*args):
      total=0
      for i in args:
      total+=i                                                      #total = total + i
      return total
  
  print(f"The total is {addition(5,23)}")
  print(f"The total is {addition(5,1,2,8,3)}")

Output:
The total is 28
The total is 19

Now, we know how to use positional, keyword arguments and *args. Let us understand how we can use mix of these arguments.

Instead of *args, we have used *a here as we know *args is just a notation.

  def salary(bonus,*a):
      ctc = 0
      for i in a:
          ctc += i
      return ctc + bonus
  
  ctc = salary(1000,2000,2000,2000)
  print(ctc)

Output:
10000

Try using *args before positional argument.

  def salary(*a,bonus):
      ctc = 0
      for i in a:
          ctc += i
      return ctc + bonus
  
  ctc = salary(1000,2000,2000,2000)
  print(ctc)

reserved_keywords

Share price was Rs.10 at day 1, Someone sold his/her shares in 3 consecutive days at Re.1 increase on each day.

  def shares_value(share_price,*shares):
      total_value = 0
      for i in shares:
          total_value += i * share_price                                                  #total_value = total_value + (i * share_price)
          share_price += 1
      return total_value
  
  total_value = shares_value(10,5,2,1)
  print(f"Total Shares value is: Rs.{total_value}")

Output:
Total Shares value is: Rs.84

Share price was Rs.10 at day 1, Someone sold his/her shares in 3 consecutive days at Re.1 increase on each day.
Person also received dividend of Rs.100 on shares when he/she sold last stock of shares.

  def shares_value(share_price,dividend,*shares):
      total_value = 0
      for i in shares:
          total_value += i * share_price                                                  #total_value = total_value + (i * share_price)
          share_price += 1
      return total_value + dividend
  
  total_value = shares_value(10,100,5,2,1)
  print(f"Total Shares value is: Rs.{total_value}")

Output:
Total Shares value is: Rs.84

Let us try to make above dividend argument as keyword argument.

  def shares_value(share_price,dividend,*shares):
      total_value = 0
      for i in shares:
          total_value += i * share_price                                                  #total_value = total_value + (i * share_price)
          share_price += 1
      return total_value + dividend
  
  total_value = shares_value(10,dividend=100,5,2,1)
  print(f"Total Shares value is: Rs.{total_value}")

reserved_keywords

Always, keyword arguments should follow positional arguments.
We noticed that *args is nothing but a set of positional arguments.

  def shares_value(share_price,*shares,dividend):
      total_value = 0
      for i in shares:
          total_value += i * share_price                                                  #total_value = total_value + (i * share_price)
          share_price += 1
      return total_value + dividend
  
  total_value = shares_value(10,5,2,1,dividend=100)
  print(f"Total Shares value is: Rs.{total_value}")

Output:
Total Shares value is: Rs.184