20TD02U_Functions and Methods - itnett/FTD02H-N GitHub Wiki

Remembering: "What is a function? List the parts of a function definition."

Function: A function is a block of code that performs a specific task, is reusable, and can be executed when called. Functions help to organize code, make it more readable, and allow for code reuse.

Parts of a Function Definition:

  1. Function Name: The name by which the function can be called.
  2. Parameters: Variables passed to the function.
  3. Body: The block of code that performs the task.
  4. Return Statement: The value or output that the function returns (optional).

Example Function Definitions:

# Function to add two numbers
def add(a, b):
    return a + b

# Function with no parameters
def greet():
    print("Hello, world!")

Understanding: "Describe the difference between a function and a method. Provide examples."

Difference Between Function and Method:

  • Function:
    • A function is a standalone block of code that can be called independently.
    • It is not bound to any object or class.

Example:

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

result = add(2, 3)
print(result)  # Output: 5
  • Method:
    • A method is a function that is associated with an object or class.
    • It is called on an instance of a class and can access or modify the data within that instance.

Example:

class Calculator:
    def add(self, a, b):
        return a + b

calc = Calculator()
result = calc.add(2, 3)
print(result)  # Output: 5

Applying: "Write a function to calculate the factorial of a number. Explain how it works."

Function to Calculate Factorial:

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

# Example usage
print(factorial(5))  # Output: 120

Explanation:

  • The function factorial takes an integer n as an argument.
  • It checks if n is 0 or 1, in which case it returns 1 (base case).
  • If n is greater than 1, it returns n multiplied by the factorial of n - 1 (recursive case).
  • This process continues until the base case is reached, resulting in the product of all positive integers up to n.

Analyzing: "Analyze the efficiency of recursive vs. iterative function implementations."

Recursive Implementation:

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

Iterative Implementation:

def factorial_iterative(n):
    result = 1
    for i in range(1, n + 1):
        result *= i
    return result

Efficiency Analysis:

  • Recursive:

    • Space Complexity: O(n) due to call stack.
    • Time Complexity: O(n).
    • Pros: Simple and elegant for small n.
    • Cons: Can lead to stack overflow for large n.
  • Iterative:

    • Space Complexity: O(1) as no additional call stack is used.
    • Time Complexity: O(n).
    • Pros: More efficient in terms of memory.
    • Cons: Slightly more complex code compared to recursion.

Evaluating: "Evaluate the readability and maintainability of functions with different complexities."

Simple Function:

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

Complex Function:

def process_data(data):
    result = []
    for item in data:
        if isinstance(item, dict):
            for key, value in item.items():
                if key == 'target' and isinstance(value, list):
                    result.extend(value)
                elif key == 'target' and isinstance(value, dict):
                    result.append(value)
    return result

Evaluation:

  • Readability:

    • Simple functions are easy to read and understand.
    • Complex functions require careful documentation and clear variable naming to maintain readability.
  • Maintainability:

    • Simple functions are easier to maintain due to their straightforward logic.
    • Complex functions should be broken down into smaller, manageable sub-functions to enhance maintainability.

Creating: "Design a set of reusable functions for a given application. Explain your design choices."

Application: Data Analysis

Reusable Functions:

  1. Load Data:

    import pandas as pd
    
    def load_data(file_path):
        """
        Load data from a CSV file.
        :param file_path: str
        :return: DataFrame
        """
        return pd.read_csv(file_path)
    
  2. Clean Data:

    def clean_data(df):
        """
        Clean the DataFrame by filling missing values.
        :param df: DataFrame
        :return: DataFrame
        """
        df.fillna(0, inplace=True)
        return df
    
  3. Analyze Data:

    def analyze_data(df):
        """
        Perform data analysis by calculating summary statistics.
        :param df: DataFrame
        :return: dict
        """
        summary = {
            'mean': df.mean(),
            'median': df.median(),
            'std': df.std()
        }
        return summary
    
  4. Visualize Data:

    import matplotlib.pyplot as plt
    
    def visualize_data(df):
        """
        Create a bar plot of the DataFrame.
        :param df: DataFrame
        """
        df.plot(kind='bar')
        plt.show()
    

Design Choices:

  • Modularity: Each function performs a specific task, making the code easy to manage and reusable.
  • Clarity: Function names and parameters are self-explanatory, enhancing readability.
  • Documentation: Docstrings provide clear descriptions of each function’s purpose and usage.

Example Usage:

data = load_data('data.csv')
cleaned_data = clean_data(data)
summary = analyze_data(cleaned_data)
visualize_data(cleaned_data)

print(summary)

This set of functions demonstrates a structured approach to data analysis, promoting code reuse and maintainability.