5th Week Python Experience

5th Week Python Experience

Photo by Riku Lu on Unsplash

Functions

In Python, a function is a block of organized, reusable code that performs a specific task. Functions provide better modularity and code reusability by allowing you to break down a program into smaller, manageable pieces. Here's the basic syntax for defining a function in Python:

def function_name(parameters):
    """docstring"""
    # function body
    # statements
    return value

Let's break down each component:

  1. def: This keyword is used to define a function.

  2. function_name: This is the identifier for the function. It should follow the same rules as variable names.

  3. parameters: These are optional inputs that the function can accept. Parameters are enclosed within parentheses (). If a function doesn't take any parameters, you still need to include empty parentheses ().

  4. docstring: This is an optional documentation string that describes what the function does. It's enclosed within triple quotes """ """ and is placed immediately after the function definition. Writing descriptive docstrings is a good practice as it helps other programmers understand the purpose of your function.

  5. Function body: This is the block of code that performs the specific task of the function. It is indented under the function definition.

  6. return: This keyword is used to specify the value that the function should return when it's called. The return statement is optional. If omitted, the function returns None.

Here's an example of a simple function that adds two numbers:

def add_numbers(a, b):
    """This function adds two numbers"""
    return a + b

# Calling the function
result = add_numbers(5, 3)
print(result)  # Output: 8

In this example:

  • The function is named add_numbers.

  • It takes two parameters a and b.

  • The docstring describes what the function does.

  • The function body consists of a single statement that adds a and b.

  • The return statement returns the sum of a and b.

  • Finally, the function is called with arguments 5 and 3, and the result is printed.

Another Example : For finding discounted price .

def discount(price, discount):
  a=price * (1 - discount / 100)
  return (a)

price = int(input("Enter the price: "))
discount_input = int(input("Enter the discount: "))

print(discount(price, discount_input))

Some more examples on function for List :

#fuctions on lists

#fuction to find 1st element in list

l=[1,2,3,4,5,6,7,8,9,10]
def  first_element(l):
  return l[0]

print(first_element(l))

#fuction to find last element in list
def last_element(l):
  return l[-1]

print(last_element(l))

#function to find minimun element in list
def min(l):
  mini=100
  for i in range(len(l)):
    if l[i]<mini :
      mini=l[i]
  return mini

print(min(l)) 

#function to find avg of all number in a list

def avgoflist(l):
  sum=0
  for i in range(len(l)):
    sum=sum + l[i]
  avg=sum/len(l)
  return avg

print (avgoflist(l))

Example: function calling another function for sorting a list .

Moduling a large problem in to small parts

from random import randint as r
# initialise a marix to zero 
def initialise_mat(dim):
  c=[]
  for i in range(dim) :  #c[i][j]=0 will not work a j are not initiated yet
    c.append([])   

  for i in range(dim):
    for j in range(dim):
      c[j].append(0)
  return c

#dot product 
def dotproducct(u,v):
  ans=0 
  dim=len(u)
  for i in range(dim):
    ans=ans+(u[i]*v[i])

  return ans

#row of a matrix finder 
def row(M,i):
  l=[ ]
  dim=len(M)
  for k in range(dim):  
    l.append(M[i][k])

  return l

#column of a matrix finder
def column(M,j):
  l=[]
  dim=len(M)
  for k in range(dim):
    l.append(M[k][j])
  return l

#matrix multiplication
def mat_mul(A,B):
  dim=len(A)
  c=initialise_mat(dim)
  for i in range(dim):
    for j in range(dim):
      c[i][j]=dotproducct(row(A,i),column(B,j))
  return c

# generating 2 random 3x3 matrix
A,B=[],[]
for i in range(3):
  A.append([])
  for j in range(3):
    A[i].append(r(1,10))

for i in range(3):
  B.append([])
  for j in range(3):
    B[i].append(r(1,10))

print(f'A={A}')
print(f'A={B}')
print (f'AXB = { mat_mul(A,B)}')

Let's break down how functions are used to modularize and solve the problem of matrix multiplication in the provided code:

  1. initialize_mat(dim):

    • This function initializes a square matrix of dimension dim with all elements set to zero. It returns the initialized matrix.

    • It modularizes the task of creating a matrix, making it reusable whenever a zero-initialized matrix is needed.

  2. dotproduct(u, v):

    • This function computes the dot product of two vectors u and v.

    • It modularizes the computation of the dot product, making it reusable and separating it from the main matrix multiplication logic.

  3. row(M, i):

    • This function extracts the i-th row from matrix M.

    • It abstracts the process of accessing a row from a matrix, making the main matrix multiplication function cleaner and easier to understand.

  4. column(M, j):

    • This function extracts the j-th column from matrix M.

    • Similar to the row function, it abstracts the process of accessing a column from a matrix.

  5. mat_mul(A, B):

    • This function performs matrix multiplication between matrices A and B.

    • It utilizes the previously defined functions like dotproduct, row, and column to modularize the process of matrix multiplication.

    • By breaking down the task into smaller, manageable functions, the main matrix multiplication function becomes more readable, easier to debug, and reusable.

Overall, by using functions, the code achieves modularity, which leads to better organization, readability, and maintainability. Additionally, it demonstrates the power of breaking down a complex problem into smaller, more manageable tasks, each handled by a separate function.

Also for this code also we can import NumPy and solve it easily in some few lines of code ,, through this example i am showing you how to break down a large problem in to simple small pieces of functions and call them as we like .

Recursion

Recursion in Python (and in programming in general) is a technique where a function calls itself to solve a smaller instance of the same problem. It's like when you're trying to solve a big problem, and you realize that it's similar to a smaller problem you've already solved. Instead of solving the smaller problem all over again, you can just call the same method you used to solve the smaller problem. OR it is like calling a specific function in that same function again and again till it comes to a basic case whose value is pre-defined .

Here's a simple explanation using a classic example: factorial calculation.

Let's say you want to find the factorial of a number. The factorial of a number n is the product of all positive integers less than or equal to n. For example, the factorial of 5 (written as 5!) is 5 x 4 x 3x 2 x 1 = 120.

Now, if you want to write a Python function to calculate the factorial of a number, you can use recursion. Here's how it works:

  1. If the number is 0 or 1, the factorial is 1.

  2. Otherwise, the factorial of n is n times the factorial of n-1.

Here's how you can write this in Python:

def factorial(n):
    if (n == 0 or n == 1):
        return 1
    else:
        return n * factorial(n - 1)

When you call factorial(5), here's what happens:

  • factorial(5) calls factorial(4)

  • factorial(4) calls factorial(3)

  • factorial(3) calls factorial(2)

  • factorial(2) calls factorial(1)

  • factorial(1) returns 1

  • factorial(2) returns 2 * 1 = 2

  • factorial(3) returns 3 * 2 = 6

  • factorial(4) returns 4 * 6 = 24

  • factorial(5) returns 5 * 24 = 120

And that's how recursion works! It's a powerful technique for solving problems by breaking them down into smaller, simpler instances until you reach a base case (in this example, n = 0 or n = 1).

Example2 .

#recursion in python
#sum of n natural numbers
def sum(n):
  if(n==1):
    return 1
  else:
    return n+sum(n-1)

print(sum(10))

Example3.


#compound interest
def comp(p,n,i): #p=principalamount , n=number of years , i=interest rate
  if(n==1):
    return p*(i/100)
  else:
    return (comp(p,n-1))*(i/100)

print(comp(2000,3,10))

In mathematical terms its like this equation given below:

Types of function arguments

Positional arguments

All functions that we have seen so far have used positional arguments. Here, the position of an argument in the function call determines the parameter to which it is passed.

keyword arguments

These are arguments that are passed to the function by name. This means that you can pass the arguments in any order, as long as you specify the name of the argument.

Default arguments

Parameters that are assigned a value in the function definition are called default parameters. An argument corresponding to a default parameter can be passed as a positional argument or as a keyword argument. Default parameters always come at the end of the parameter list in a function definition.

some extra shit :

why dose it prints none ?

we are getting a None printed at the end of the execution of our code. This is because the add function does not explicitly return anything. By default, Python functions return None if no return statement is specified.

must see this also :

The scope of variable

The region in the code where a name can be referenced is called its scope. If we try to reference a variable outside its scope, the interpreter will throw aNameError.

Local VS Global :-

In the above example, the scope of the name x is local to the function ; x has a meaningful existence only inside the function and any attempt to access it from outside the function is going to result in an error

The name y is accessible from within the function as well. We say that the scope of y is global. That is, it can be referenced from any where within the program — even inside a function — after it has been defined for the first time.

see this example below and think :

here X is a global variable (can be called anywhere in the whole code ) and x is also a local variable for myfuncation1 and myfunction2 (only can be called within the scope like a specific block or function )

Types of functions

  1. Built-in functions : So far we have been freely using built-in functions like print(), int(), len() and so on.

  2. Library functions : These functions are the built-in functions i.e., they are predefined in the library of the python, such as sqrt(), log() , random() and so on.

  3. String methods or functions : String functions are used to manipulate a string , some of them are lower(), upper(), strip() and so on.

  4. User defined functions : User-defined functions are functions that we use to organize our code.

So these were the Things that I learnt in week 5 , functions , arguments , scope of variable all taught me something new .. hoping to get more info in week 6 and share with you all in simplest explanation possible. Happy Learnings everyone..