Python Tutorial with Examples

python python interview questions python examples python practice python coding python oops python advanced python topics python programming python exercises python tips python for beginners python for interviews python tutorials python tutorial learn python python basics python guide python course KOTHA ABHISHEK

Introduction to Python

Python is a high-level, interpreted, general-purpose programming language known for its simplicity, readability, and broad applicability. It was created by Guido van Rossum and released in 1991.

  • Easy to Learn: Python has simple, English-like syntax that makes it easy for beginners to start programming.
  • Versatile: You can use Python for web development, data analysis, artificial intelligence, automation, scripting, and more.
  • Cross-platform: Python runs on Windows, Linux, macOS, and many other platforms.
  • Large Standard Library: Python comes with many built-in modules and packages to perform a wide range of tasks.
  • Community Support: Python has a vast, active community and plenty of learning resources.

Hello World Example:



                

Python Comments

Comments in Python are used to make code more readable and to provide explanations or notes for yourself and others. Comments are ignored by the Python interpreter and do not affect your program's execution.

  • Single-line comment: Use the # symbol before your comment.
    Example:


                
  • Multi-line comments: Python does not have a dedicated multi-line comment syntax. You can use multiple # symbols on separate lines, or triple quotes ''' or """ for documentation strings (docstrings, not true comments).
Tip: Use comments to explain complex code, mark TODOs, or temporarily disable code during development.

Python Indentation

Indentation in Python refers to the spaces at the beginning of a code line. Unlike many other programming languages that use braces ({}) to define code blocks, Python uses indentation. Proper indentation is very important in Python, as it determines the grouping of statements.

  • Code blocks such as those for functions, loops, conditionals, and classes must be indented by the same number of spaces.
  • By convention, 4 spaces per indentation level is recommended (do not mix tabs and spaces).

Example:



                
  • Incorrect indentation will result in an IndentationError and the program will not run.
Tip: Always use the same number of spaces for indentation within a block. IDEs and code editors can help you manage indentation automatically.

Taking Input in Python

You can use the input() function to take user input in Python. This function reads a line from the user as a string.

  • Syntax: variable = input("Prompt message")
  • The value returned by input() is always a string. If you need another type (like int), you must convert it.

Example:



                
  • To get numeric input, convert the string:
    # age = int(input("Enter your age: "))
Tip: Always convert input to the needed type, and handle possible errors with try-except blocks if needed.

Printing Output in Python

The print() function is used to display output to the screen in Python. You can print text, numbers, variables, and even the results of expressions.

  • Basic usage: Pass the value you want to display as an argument to print().
  • You can print multiple items by separating them with commas.
  • Formatting output: You can use f-strings (Python 3.6+) or str.format() to format your output.

Example:



                
Tip: Use print() frequently to debug your code and check the values of variables.

Printing Variables in Python

In Python, you can print the value of variables by passing them as arguments to the print() function. You can print single or multiple variables at once, and you can also format the output using f-strings or the str.format() method.

  • Printing a single variable: Just pass the variable to print().
  • Printing multiple variables: Separate them with commas in the print() function.
  • Formatted output: Use f-strings (f"...") or str.format() for more control over how variables appear in the output.

Example:



                
Tip: Use f-strings (e.g., f"{variable}") for readable and convenient variable printing in Python 3.6 and above.

Taking Multiple Inputs in Python

You can take multiple inputs from the user in a single line using the input() function and the split() method. This is useful for getting several values at once, such as numbers or words separated by spaces.

  • Basic usage:
    a, b = input("Enter two values: ").split()
  • For numeric input: Use map() to convert each input to an integer or float.
    a, b = map(int, input("Enter two numbers: ").split())
  • For a list of values: Use list(map(int, input().split())) to create a list of integers from input.
Example 1: Split input into variables


                
Example 2: Taking multiple integers as a list


                
Tip: Always convert input values to the required type (like int or float) as input() returns strings by default.

Taking Conditional Input in Python

Sometimes you may want to take input from the user and process it based on certain conditions. This is often done by combining the input() function with if, elif, and else statements.

  • Conditional input means you ask the user for input, then perform actions depending on the value entered.
  • Usually, the input is converted to the required type (e.g., int or float) before checking conditions.
Example 1: Check if a number is positive, negative, or zero


                
Example 2: Check if user entered "yes" or "no"


                
Example 3: Age check for voting eligibility


                
Tip: Always validate and convert your input to the proper type before using it in conditions to avoid errors.

Changing the Type of Input in Python

By default, the input() function in Python returns data as a string. If you want to work with numbers or other types, you need to convert (cast) the input to the required type using functions like int(), float(), or bool().

  • To integer: int(input("Enter a number: "))
  • To float: float(input("Enter a decimal: "))
  • To boolean: bool(input("Enter True/False: ")) (rarely used; usually you check the string value)
Example 1: Convert input to integer


                
Example 2: Convert input to float


                
Example 3: Convert multiple inputs to integers using map()


                
Example 4: Check input type and demonstrate common mistake


                
Tip: Always convert your input to the needed type to avoid type errors in calculations or comparisons!

Python Variables

Variables in Python are used to store data values. You don’t need to declare the type of a variable explicitly—Python figures it out automatically based on the assigned value.

  • Variable names can contain letters, numbers, and underscores, but must not start with a number.
  • Variables are case-sensitive (age and Age are different).
  • You can change the value and the data type of a variable at any time.
Example 1: Assigning and printing variables


                
Example 2: Changing variable values and types


                
Example 3: Multiple assignment


                
Tip: Use descriptive variable names for better readability.
Common mistake: Don’t use spaces or special characters in variable names.

Scope of a Variable in Python

Scope refers to the region of a program where a variable is recognized. Python has different types of variable scopes:

  • Local Scope: Variables declared inside a function are local to that function.
  • Global Scope: Variables declared outside any function are global and can be accessed anywhere in the code.
  • Enclosed (Nonlocal) Scope: Variables in the local scope of enclosing functions (nested functions).
  • Built-in Scope: Names preassigned in Python (like print(), len()).
Example 1: Local vs Global Variable


                
Example 2: Using global Keyword


                
Example 3: Enclosed (Nonlocal) Scope


                
Tip: Understanding scope helps prevent bugs and makes your code more predictable. Use global and nonlocal sparingly!

Object Reference in Python

In Python, variables are not containers of values—they are references to objects stored in memory. This concept is critical when working with mutable types like lists or dictionaries.

  • Assignment: Creates a new reference, not a new object.
  • id(): Returns the memory address (identity) of an object.
  • Mutable vs Immutable: Mutables can be changed through references; immutables cannot.
  • Copying: Use copy() or deepcopy() to avoid shared references.
Example 1: Assignment Creates Reference


                
Example 2: Changing One Affects the Other (Mutable)


                
Example 3: Memory Address with id()


                
Example 4: Shallow Copy


                
Example 5: Deep Copy


                
Example 6: Function Modifying Mutable Object


                
Tip: Remember that variables in Python are just labels pointing to objects. Always be careful when working with mutable types like lists and dictionaries!

Deleting a Variable in Python

In Python, you can delete a variable or object reference using the del statement. This removes the binding between the name and the object it refers to.

  • del variable: Removes the variable name. If no other references exist, the object is garbage collected.
  • del list[index]: Deletes an item at a specific index in a list.
  • del dict[key]: Deletes an item from a dictionary.
  • del variable1, variable2: Delete multiple variables at once.
Example 1: Deleting a Variable


                
Example 2: Deleting List Element


                
Example 3: Deleting Dictionary Key


                
Example 4: Deleting Multiple Variables


                
Example 5: Deleting Object Attribute


                
Tip: Use del cautiously. It removes the name, not the object unless it's the last reference. Avoid using it unless necessary, especially in large programs.

Swapping Two Variables in Python

Swapping means exchanging the values of two variables. Python offers multiple ways to do this.

  • Using Temporary Variable: A traditional way used in most programming languages.
  • Tuple Unpacking: Pythonic way using a, b = b, a.
  • Arithmetic Operations: Swapping without a temp variable (only for numbers).
  • XOR Method: A bitwise technique (used in low-level logic).
Example 1: Using a Temporary Variable


                
Example 2: Pythonic Way (Tuple Unpacking)


                
Example 3: Using Arithmetic Operators (Numbers Only)


                
Example 4: Using XOR Bitwise Operator


                
Tip: The most Pythonic and recommended way to swap is using a, b = b, a. It’s clean and efficient.

Counting Characters in a String in Python

Python provides multiple ways to count characters in a string. You can do it manually using loops, or use built-in tools like count() and collections.Counter.

  • Manual Loop: Use a dictionary and loop through characters.
  • count(): Count specific characters directly.
  • collections.Counter: Quickly count all characters.
  • Case-Insensitive: Convert to same case before counting.
  • Filter-based Count: Count only letters, digits, or special characters.
Example 1: Manual Count using Dictionary


                
Example 2: Using count() for a Specific Character


                
Example 3: Using collections.Counter


                
Example 4: Case-Insensitive Counting


                
Example 5: Count Letters, Digits & Specials Separately


                
Tip: For quick frequency count, collections.Counter is powerful and readable.

Arithmetic Operators in Python

Python provides several arithmetic operators to perform mathematical operations. These operators work with numbers (integers and floats).

  • + – Addition
  • - – Subtraction
  • * – Multiplication
  • / – Division (returns float)
  • // – Floor Division (returns integer result)
  • % – Modulus (returns remainder)
  • ** – Exponentiation (power)

Example – Using arithmetic operators:



                
Tip: Use // for integer division and ** to raise numbers to a power.

Comparison Operators in Python

Comparison operators are used to compare two values. They return a boolean value: True or False.

  • == – Equal to
  • != – Not equal to
  • > – Greater than
  • < – Less than
  • >= – Greater than or equal to
  • <= – Less than or equal to

Example – Comparing variables:



                
Tip: Comparison operators are commonly used in if statements to control program flow.

Logical Operators in Python

Logical operators are used to combine conditional statements. They return boolean values based on the logic applied.

  • and – Returns True if both statements are true
  • or – Returns True if at least one statement is true
  • not – Reverses the result, returns False if the result is true

Example – Using logical operators with conditions:



                
Tip: Logical operators are often used in if and while statements for combining multiple conditions.

Bitwise Operators in Python

Bitwise operators operate on integers at the binary level. These are used for performing bit-by-bit operations.

  • & – Bitwise AND
  • | – Bitwise OR
  • ^ – Bitwise XOR
  • ~ – Bitwise NOT
  • << – Left Shift
  • >> – Right Shift

Example – Bitwise operations between integers:



                
Tip: Bitwise operations are often used in low-level programming, masking operations, and performance optimizations.

Assignment Operators in Python

Assignment operators are used to assign values to variables. Python also supports shorthand assignment operators that combine arithmetic or bitwise operations with assignment.

  • =  → Assigns value from right to left
  • += → Add and assign
  • -= → Subtract and assign
  • *= → Multiply and assign
  • /= → Divide and assign (float division)
  • //= → Floor divide and assign
  • %= → Modulus and assign
  • **= → Exponent and assign
  • &= → Bitwise AND and assign
  • |= → Bitwise OR and assign
  • ^= → Bitwise XOR and assign
  • <<= → Left shift and assign
  • >>= → Right shift and assign

Example – Using assignment operators:



                
Tip: Compound assignment operators make your code cleaner and reduce redundancy, especially in loops and mathematical operations.

Identity Operators in Python

Identity operators are used to compare the memory locations of two objects. They check whether two variables refer to the same object in memory.

  • is  → Returns True if two variables refer to the same object
  • is not → Returns True if two variables refer to different objects

Example – Using identity operators:



                
Note: Use is for checking if two variables refer to the exact same object. For value equality, use ==.

Membership Operators in Python

Membership operators are used to test whether a value is present in a sequence (like string, list, tuple, set, or dictionary).

  • in  → Returns True if the value is found in the sequence
  • not in → Returns True if the value is not found in the sequence

Example – Using membership operators:



                
Tip: When using in with dictionaries, it only checks for keys, not values. Use value in dict.values() to check values.

Ternary Operator in Python

The ternary operator is a one-line shorthand for if-else statements. It allows conditional assignments or expressions.

Syntax:

result = value_if_true if condition else value_if_false
    

Example – Using ternary operator to assign a value:



                
Tip: Use ternary operators to keep your code clean when you have a simple if-else condition inside assignments.

Python Data Types

Python has various built-in data types that are used to store different kinds of values. Every value in Python has a data type. You can check the type using the built-in type() function.

  • Numeric Types: int, float, complex
  • Sequence Types: str, list, tuple
  • Mapping Type: dict
  • Set Types: set, frozenset
  • Boolean Type: bool
  • Binary Types: bytes, bytearray, memoryview
  • None Type: NoneType

Example – Using different data types and checking their types:



                

Example – Checking if a variable is of a specific type:



                

Extra Tip: You can convert between types using functions like int(), str(), float(), list(), etc.

Useful Note: Python is dynamically typed, meaning you don’t need to declare the type of variable beforehand. The interpreter infers the type automatically.

Conditional Statements in Python

Conditional statements allow you to execute specific blocks of code based on certain conditions. Python uses if, elif, and else for decision making.

  • if – Executes a block of code if the condition is true.
  • elif – Checks another condition if the previous ones were false.
  • else – Executes a block of code if none of the above conditions are true.

Syntax:

if condition1:
    # code block
elif condition2:
    # code block
else:
    # code block
    

Example – Basic conditional:



                

Example – Using multiple elif conditions:



                

Example – Nested if statements:



                
Tip: Indentation is crucial in Python. Make sure all blocks of code under if, elif, and else are properly indented.

Match-Case Statement in Python

The match-case statement (introduced in Python 3.10) is similar to switch-case in other languages. It allows pattern matching on values and provides a clean way to handle multiple conditions.

Syntax:

match variable:
    case pattern1:
        # block of code
    case pattern2:
        # block of code
    case _:
        # default case
        
_ acts like the default case.

  • Cleaner than nested if-elif-else.
  • Supports patterns: literals, variable capture, sequences, classes, and more.
  • Python 3.10+ feature — will not work in earlier versions.

Example 1 – Simple Integer Match:



                

Example 2 – Matching Strings:



                

Example 3 – Tuple Matching:



                
Tips:
  • match-case improves readability for multi-condition branching.
  • Each case can destructure values — like unpacking tuples or lists.
  • Use _ as the wildcard/default matcher.
  • Always test your code with Python 3.10+ for compatibility.

Loops in Python

Loops are used to execute a block of code repeatedly. Python provides two main types of loops: for and while. Loops help in automation and iterating over data structures like lists, tuples, strings, etc.

1. For Loop

The for loop is used for iterating over a sequence. It automatically goes through each element in the sequence.

Example – Iterating over a list:



                

2. While Loop

The while loop executes as long as a condition is True. It is useful when the number of iterations is not known beforehand.

Example – Counting from 1 to 5:



                

3. Loop Control Statements

  • break – exits the loop immediately
  • continue – skips the current iteration and continues with the next
  • pass – does nothing, acts as a placeholder

Example – Using break and continue:



                

4. Nested Loops

A loop inside another loop. Useful when working with 2D lists, patterns, tables, etc.

Example – Multiplication Table (1 to 3):



                
Tip: Always ensure that the loop condition eventually becomes false to avoid infinite loops.

Strings in Python

A string in Python is a sequence of Unicode characters enclosed in single, double, or triple quotes. Strings are immutable, meaning they cannot be changed after creation.

Creating Strings

  • single_quote = 'Hello'
  • double_quote = "World"
  • triple_quote = '''This is a multi-line string'''

String Operations

  • Concatenation: str1 + str2
  • Repetition: str * 3
  • Access by Index: str[0]
  • Slicing: str[1:4]
  • Length: len(str)
  • Membership: 'a' in str

Useful String Methods

  • str.upper() – Converts to uppercase
  • str.lower() – Converts to lowercase
  • str.strip() – Removes leading/trailing whitespace
  • str.replace('a', 'b') – Replaces substring
  • str.split() – Splits into a list
  • str.find('x') – Finds index of first occurrence
  • str.startswith('Hello'), str.endswith('!')

Example – Working with Strings



                
Tip: Strings are widely used in web scraping, APIs, file handling, and UI messages. Mastering string methods will make data handling easier.

Python Lists

A list in Python is an ordered, mutable (changeable) collection of items. Lists can contain elements of different data types such as integers, strings, floats, and even other lists.

Key Features of Lists:

  • Ordered: Items have a defined order, and that order will not change unless explicitly modified.
  • Mutable: You can modify, add, or remove elements after the list is created.
  • Heterogeneous: A single list can contain different data types.
  • Indexable: You can access elements using indexes, starting from 0.

Creating a List:



                

Accessing List Elements:



                

Modifying a List:



                

Removing Elements:



                

Useful List Functions:



                
Tip: Lists are very flexible and widely used in Python for data handling, iteration, and more. You can loop through them, use them in list comprehensions, and nest them to build complex structures.

Python Tuples

A tuple is an ordered, immutable collection of items. Tuples are similar to lists, but once created, their values cannot be changed. Tuples are defined using parentheses ().

Why Use Tuples?

  • Tuples are faster than lists (due to immutability).
  • Used to protect data from modification.
  • Can be used as dictionary keys (lists cannot).

Tuple Creation



                

Accessing Tuple Elements



                

Tuple Methods

Tuples support only two methods:

  • count() – Returns the number of times a value appears in the tuple.
  • index() – Returns the index of the first occurrence of a value.


                

Tuple Unpacking

Tuple unpacking allows you to assign tuple values to multiple variables at once.



                

Nested Tuples

Tuples can contain other tuples (or lists).



                
Tip: Since tuples are immutable, if you need to change values, consider converting to a list first.

Python Dictionaries

Dictionaries in Python are unordered, mutable collections of key-value pairs. Each key is unique and is used to access the associated value.

Syntax:

my_dict = {"name": "Alice", "age": 25, "city": "New York"}
  • Keys must be immutable (like strings, numbers, tuples).
  • Values can be of any data type (string, list, dict, etc.).
  • Dictionaries are created using curly braces {}.

Example – Basic Dictionary Operations:



                

Common Dictionary Methods:

  • dict.keys() – returns all keys
  • dict.values() – returns all values
  • dict.items() – returns key-value pairs
  • dict.update() – updates one dict with another
  • dict.pop(key) – removes the key and returns its value

Example – Dictionary Methods:



                

Looping Through a Dictionary:



                
Tip: Dictionaries are perfect when you want to store and access data using meaningful keys instead of numeric indexes.

Python Sets

A set is an unordered collection of unique elements. Sets are mutable (can add or remove items) but do not allow duplicate values. They are commonly used when the existence of an item is more important than the order or frequency.

Key Properties:

  • Unordered
  • Mutable (can add/remove items)
  • No duplicate elements allowed
  • Can contain elements of different data types (e.g., int, str)

Creating a Set:



                

Common Set Operations:



                

Modifying a Set:



                

Other Useful Set Methods:

  • add(item) – Adds a single item.
  • update([list]) – Adds multiple items.
  • remove(item) – Removes item (raises error if not present).
  • discard(item) – Removes item (no error if not present).
  • clear() – Removes all items.
  • pop() – Removes and returns a random item.
  • copy() – Returns a shallow copy.

Example – Updating and Clearing a Set:



                
Tip: Sets are very useful for removing duplicates from lists and for performing mathematical set operations like union and intersection.

Python Arrays

In Python, an array is a data structure that holds a collection of items of the same data type. Although Python lists can also store multiple items, arrays (from the array module) are more memory-efficient when working with numeric data types.

Why Use Arrays?

  • Better performance for large numeric datasets
  • Stores items of the same data type (e.g., all integers or all floats)
  • Supports efficient looping and memory operations

Importing and Creating an Array:



                

Supported Type Codes:

  • 'i' – Signed integer
  • 'f' – Float
  • 'd' – Double precision float
  • 'u' – Unicode character
  • ...and more from the array module

Adding, Removing, and Modifying Elements:



                

Looping Through an Array:



                

Useful Methods:

  • append(x) – Adds an item to the end
  • insert(i, x) – Inserts at index i
  • remove(x) – Removes first occurrence of x
  • pop([i]) – Removes and returns element at index i
  • index(x) – Returns index of first occurrence
  • reverse() – Reverses the array in place
  • buffer_info() – Memory address and item count

Example – Using Array Methods:



                
Tip: For scientific computing or more advanced numerical operations, consider using NumPy arrays which offer more features and better performance.

List Comprehension in Python

List comprehension is a concise and elegant way to create new lists by applying an expression to each item in an iterable. It’s faster and more readable than using traditional loops in many cases.

Why Use List Comprehension?

  • Shorter and cleaner syntax compared to for loops
  • Often more efficient in performance
  • Can include conditions (like if) for filtering

Basic Syntax:

new_list = [expression for item in iterable if condition]

Example – Create a List of Squares:



                

With Condition – Get Even Numbers Only:



                

Nested Loops in List Comprehension:



                

Example – Convert List of Strings to Uppercase:



                

Using List Comprehension with Functions:



                
Tip: List comprehension is also available for dictionaries and sets. But keep it simple—don’t overcomplicate logic within the brackets for readability.

OrderedDict and defaultdict in Python

🔹 OrderedDict

OrderedDict is a subclass of the built-in dict from the collections module. It remembers the order in which keys are inserted (important before Python 3.7).

  • Preserves insertion order of keys.
  • Useful when order of items matters (e.g., JSON formatting, cache behavior).

Example:



                

🔹 defaultdict

defaultdict is another subclass of dict from the collections module. It provides a default value for a nonexistent key, avoiding KeyError.

  • Automatically initializes missing keys with a default type (e.g., int, list, str).
  • Ideal for counters, grouping, and aggregation tasks.

Example:



                
Tip: Use OrderedDict when key order matters, and defaultdict when working with grouped or missing data.

Current DateTime Display using Python

You can use Python's datetime module to get the current date and time in various formats. Below are different examples:

  • Standard 24-hour Format:
    datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    Example Output: 2025-07-09 20:10:30
  • 12-hour Format with AM/PM:
    datetime.now().strftime("%Y-%m-%d %I:%M:%S %p")
    Example Output: 2025-07-09 08:10:30 PM
  • Full Weekday and Month Name:
    datetime.now().strftime("%A, %B %d, %Y %H:%M")
    Example Output: Wednesday, July 09, 2025 20:10
  • Custom Date Format (DD-MM-YYYY):
    datetime.now().strftime("%d-%m-%Y")
    Example Output: 09-07-2025
  • Only Time:
    datetime.now().strftime("%H:%M:%S")
    Example Output: 20:10:30
  • ISO Format:
    datetime.now().isoformat()
    Example Output: 2025-07-09T20:10:30.123456
  • Unix Timestamp:
    datetime.now().timestamp()
    Example Output: 1752388230.123456

Basic Example:



                

Monthly Calendar Display using Python

Python’s built-in calendar module lets you display calendars for any month and year. It's useful for generating calendar-based outputs in CLI tools or applications.

  • Display current month calendar:
    calendar.month(2025, 7)
  • Set custom starting day (Sunday):
    calendar.setfirstweekday(calendar.SUNDAY)
  • Print full year calendar:
    calendar.calendar(2025) – prints the full calendar for the year 2025
  • Get weekday of a date:
    calendar.weekday(2025, 7, 9)
    Output: 2 (0=Monday, so 2 = Wednesday)
  • Check if a year is a leap year:
    calendar.isleap(2024)
    Output: True

Basic Example:



                

Python: Check if File Exists

In Python, you can use the os.path module or the pathlib module to check if a file exists. This is useful before reading from or writing to a file.

  • Using os.path.exists():
    os.path.exists("filename.txt")
    Returns True if the file or directory exists.
  • Check specifically for files (not directories):
    os.path.isfile("filename.txt")
  • Using pathlib.Path (Python 3.4+):
    Path("filename.txt").exists()
  • Good Practice:
    Use pathlib for modern and readable file operations.

Basic Example using os:



                

Example using pathlib:



                

Python: Functions

Functions in Python are reusable blocks of code defined with the def keyword. They perform specific tasks, accept inputs (arguments), and can return outputs. Functions improve code modularity, readability, and reusability.

Creating a Function

Use def function_name(parameters): to define a function. The function body is indented, and it can include a return statement to output a value.



                

Calling a Function

To execute a function, use its name followed by parentheses, passing any required arguments inside the parentheses.



                

Arguments

Functions can accept arguments (parameters) to process data. Arguments can be positional (order matters) or keyword-based (specified by parameter name).



                

*args (Variable Positional Arguments)

Use *args to pass a variable number of non-keyword arguments to a function. They are treated as a tuple inside the function.



                

**kwargs (Variable Keyword Arguments)

Use **kwargs to pass a variable number of keyword arguments. They are treated as a dictionary inside the function.



                

Keyword Arguments

Keyword arguments allow you to specify arguments by their parameter names, making the code more readable and flexible in order.



                

Default Parameter Value

Parameters can have default values, used when the argument is not provided during the function call.



                

Passing a List as an Argument

You can pass a list as an argument to a function, which the function can process as needed.



                

Return Values

Functions can return values using the return statement. Multiple values can be returned as a tuple.



                

The pass Statement

The pass statement is a placeholder that does nothing, used when a function (or other code block) is not yet implemented.



                

Function vs Module vs Package

  • Function: A single block of reusable code performing a specific task, defined with def.
  • Module: A Python file (e.g., math.py) containing functions, classes, or variables that can be imported.
  • Package: A directory containing multiple modules and a special __init__.py file, allowing organized import of modules.



                

Anonymous Functions (Lambda Functions)

Lambda functions are small, anonymous functions defined with the lambda keyword. They are used for short, one-off operations.



                

Recursive Functions

A recursive function calls itself to solve a problem by breaking it into smaller instances of the same problem.



                

Python: Lambda Functions

Lambda functions in Python are small, anonymous functions defined using the lambda keyword. They are used for short, one-off operations without needing a formal def function definition. Lambda functions can take multiple arguments but are restricted to a single expression. They are commonly used in functional programming contexts, such as with map(), filter(), or sorted().

  • Syntax:
    lambda arguments: expression
    Example: lambda x: x * 2 doubles the input x.
  • Use Cases:
    Ideal for short functions passed as arguments to higher-order functions like map(), filter(), or sorted().
  • Limitations:
    Limited to a single expression; cannot contain statements (e.g., print, loops) or multiple lines.
  • Good Practice:
    Use lambda functions for simple operations to keep code concise, but prefer named functions for complex logic or reusability.

Basic Example: Simple Lambda Function

This example shows how to create a basic lambda function to perform a simple calculation and use it directly or assign it to a variable.



                

Example: Lambda with Multiple Arguments

Lambda functions can take multiple arguments, allowing operations like addition or comparison on several inputs.



                

Example: Lambda with map() and filter()

Lambda functions are often used with map() to apply a function to all items in an iterable or filter() to select items based on a condition.



                

Example: Lambda with sorted()

Lambda functions can be used as the key argument in sorted() to define custom sorting logic, such as sorting a list of tuples or dictionaries.



                

Example: Lambda with Conditional Logic

Lambda functions can include conditional logic using a ternary operator for concise decision-making within the expression.



                

Python: Arrays

In Python, the term "array" typically refers to lists, which are ordered, mutable collections of items. Python also provides the array module for creating more memory-efficient arrays of uniform data types, useful for numerical data. Lists are versatile and widely used, while array module arrays are specialized for specific use cases like numerical computations. This tutorial focuses on lists as arrays and briefly covers the array module.

  • Lists as Arrays:
    Defined with square brackets [], lists can store mixed data types.
    Example: numbers = [1, 2, 3]
  • array Module:
    The array module creates arrays with a specific data type (e.g., integers, floats) using type codes.
    Example: array('i', [1, 2, 3]) for an integer array.
  • Accessing and Modifying:
    Use indexing (list[0]) and slicing (list[1:3]) to access elements. Lists and arrays are mutable, so elements can be changed.
  • Good Practice:
    Use lists for general-purpose arrays and the array module for performance-critical numerical tasks. Avoid mixing data types in array module arrays.

Basic Example: Using Lists as Arrays

This example shows how to create a list (used as an array), access elements, and perform basic operations like appending and slicing.



                

Example: Using the array Module

The array module creates arrays with uniform data types, which are more memory-efficient for numerical data. This example uses type code 'i' for integers.



                

Example: Array Operations with Loops

Lists (as arrays) can be iterated over to perform operations like summing elements or filtering based on conditions.



                

Example: Multidimensional Arrays (Nested Lists)

Lists can be nested to create multidimensional arrays (e.g., matrices). This example shows how to create and manipulate a 2D array.



                

Example: Array Sorting and Reversing

Lists (as arrays) support sorting and reversing operations using methods like sort() and reverse() or built-in functions like sorted().



                

Python: Try, Except, and Finally

Exception handling in Python uses try, except, and finally blocks to manage errors gracefully, preventing program crashes. The try block contains code that might raise an exception, except handles specific or general errors, and finally executes code regardless of whether an exception occurs. An optional else block runs if no exception is raised.

  • Try Block:
    Contains code that might raise an exception.
    Example: try: result = 10 / 0
  • Except Block:
    Catches and handles exceptions. Can specify exception types (e.g., ZeroDivisionError) or catch all exceptions.
    Example: except ZeroDivisionError: print("Cannot divide by zero!")
  • Finally Block:
    Runs regardless of whether an exception occurs, useful for cleanup tasks.
    Example: finally: print("Cleanup done.")
  • Good Practice:
    Catch specific exceptions instead of general ones, use finally for resource cleanup, and avoid complex logic in except blocks.

Basic Example: Handling a Simple Exception

This example shows a basic try-except block to handle a division-by-zero error.



                

Example: Handling Multiple Exceptions

You can handle different types of exceptions in separate except blocks to provide specific error messages.



                

Example: Using else with Try-Except

The else block runs if no exception is raised in the try block, useful for code that depends on successful execution.



                

Example: Finally for Cleanup

The finally block is used for cleanup tasks, such as closing resources, even if an exception occurs. This example simulates resource management.



                

Example: Raising Exceptions

You can raise exceptions intentionally using the raise keyword and handle them in a try-except block.



                

Python: File Handling

File handling in Python allows you to read from and write to files like text (.txt), JSON (.json), and YAML (.yml). The built-in open() function is used for text files, while modules like json and yaml handle structured data. Exception handling with try-except ensures robust file operations. Note: Since Pyodide has limited file system support, these examples show code and expected output as it would appear in a standard Python environment.

  • Opening Files:
    Use open(filename, mode) with modes like 'r' (read), 'w' (write), 'a' (append).
    Example: open('file.txt', 'r')
  • Handling JSON/YAML:
    Use json for JSON files and yaml (requires pyyaml) for YAML files to read/write structured data.
    Example: json.dump(data, file)
  • Exception Handling:
    Use try-except to handle errors like FileNotFoundError or PermissionError.
  • Good Practice:
    Always close files using file.close() or a with statement, prefer with for automatic cleanup, and validate file formats when handling JSON/YAML.

Example: Reading and Writing a Text File

This example demonstrates reading from and writing to a .txt file using the with statement for automatic file closure.


File content:
Hello, Python!
Welcome to file handling.

Example: Handling JSON Files

The json module is used to read and write JSON files, which store structured data like dictionaries or lists.


JSON content:
{'name': 'Alice', 'age': 25, 'city': 'New York'}

Example: Handling YAML Files

The yaml module (requires pyyaml) is used for YAML files, which are human-readable and often used for configuration.


YAML content:
{'server': {'host': 'localhost', 'port': 8080}, 'debug': True}

Example: Appending to a Text File

This example shows how to append data to an existing .txt file without overwriting its content.


Updated log content:
New log entry

Example: Checking File Existence Before Reading

This example uses the os.path module to check if a file exists before attempting to read it, preventing errors.


Error: data.txt does not exist!

Python: Classes and Objects

In Python, a class is a blueprint for creating objects, which are instances of the class. Classes define attributes (data) and methods (functions) to model real-world entities or abstract concepts. Objects are created from classes and can have unique attribute values. This is a core concept of Object-Oriented Programming (OOP) in Python, enabling structured and reusable code.

  • Defining a Class:
    Use class ClassName: to define a class. The __init__ method initializes object attributes.
    Example: class Person: def __init__(self, name): self.name = name
  • Creating Objects:
    Instantiate a class with obj = ClassName(args) to create an object.
    Example: person = Person("Alice")
  • Attributes and Methods:
    Attributes store data (e.g., self.name), and methods define behavior (e.g., def greet(self):).
    Example: person.name or person.greet()
  • Good Practice:
    Use descriptive class and method names, initialize attributes in __init__, and use self explicitly for instance attributes/methods.

Basic Example: Creating a Class and Object

This example defines a simple class with an __init__ method and a method to display information, then creates an object.



                

Example: Modifying Object Attributes

This example shows how to modify an object's attributes after creation and access them directly.



                

Example: Class with Multiple Methods

This example demonstrates a class with multiple methods to perform different actions, showcasing method interactions.



                

Example: Class with Class and Instance Attributes

This example shows the difference between class attributes (shared by all objects) and instance attributes (unique to each object).



                

Example: Using Objects in a List

This example demonstrates storing multiple objects in a list and iterating over them to call methods.



                

Python: Class, Static, and Instance Variables

In Python, classes use different types of variables and methods to manage data and behavior. Instance variables are unique to each object, defined in the __init__ method. Class variables are shared across all instances of a class, defined directly in the class body. Static methods (using @staticmethod) operate without accessing instance or class state, while class methods (using @classmethod) can access/modify class variables. These concepts are fundamental to Object-Oriented Programming (OOP) in Python.

  • Instance Variables:
    Unique to each object, set using self.variable = value in methods like __init__.
    Example: self.name = name
  • Class Variables:
    Shared by all instances, defined in the class body.
    Example: class Dog: species = "Canine"
  • Static Methods:
    Defined with @staticmethod, they don’t access instance (self) or class (cls) state.
    Example: @staticmethod def utility():
  • Class Methods:
    Defined with @classmethod, they access class state via cls.
    Example: @classmethod def get_species(cls):
  • Good Practice:
    Use instance variables for object-specific data, class variables for shared data, and static/class methods for utility or class-level operations. Avoid modifying class variables via instances unless intentional.

Basic Example: Instance and Class Variables

This example defines a class with instance variables (unique to each object) and a class variable (shared across all objects).



                

Example: Modifying Class and Instance Variables

This example shows how modifying a class variable affects all objects, while instance variables remain unique.



                

Example: Static Method

This example demonstrates a static method that performs a utility task without accessing instance or class state.



                

Example: Class Method with Class Variables

This example shows a class method that accesses and modifies a class variable, affecting all instances.



                

Example: Combining Instance, Class, and Static Methods

This example combines instance variables, class variables, static methods, and class methods in a single class to show their interactions.



                

Python: Constructors

In Python, a constructor is a special method used to initialize objects when they are created from a class. The primary constructor is the __init__ method, which sets up instance variables and prepares the object for use. Constructors can be parameterized (accepting arguments) or non-parameterized (default). They are automatically called when an object is instantiated, making them essential for Object-Oriented Programming (OOP) in Python.

  • __init__ Method:
    Defined as def __init__(self, ...):, it initializes instance variables.
    Example: def __init__(self, name): self.name = name
  • Parameterized Constructor:
    Accepts arguments to set instance variables during object creation.
    Example: obj = ClassName(arg1, arg2)
  • Default Constructor:
    A constructor with no parameters (except self), used for default initialization.
    Example: def __init__(self): self.value = 0
  • Good Practice:
    Use __init__ to initialize all necessary instance variables, keep constructor logic simple, and use descriptive parameter names.

Basic Example: Simple Constructor

This example shows a basic __init__ constructor that initializes instance variables for a class.



                

Example: Default Constructor

This example demonstrates a default constructor with no parameters (except self), setting default values for instance variables.



                

Example: Parameterized Constructor with Validation

This example shows a parameterized constructor that validates input parameters before initializing instance variables.



                

Example: Constructor with Default Parameters

This example demonstrates a constructor with default parameters, allowing flexible object creation.



                

Example: Constructor with Class and Instance Variables

This example combines a constructor with class and instance variables, showing how they are initialized and used.



                

Python: Inheritance

Inheritance in Python allows a class (child class) to inherit attributes and methods from another class (parent class), promoting code reuse and extensibility. The child class can extend or override the parent’s functionality. Python supports single inheritance (one parent) and multiple inheritance (multiple parents), with the super() function used to call parent class methods. Inheritance is a key feature of Object-Oriented Programming (OOP).

  • Single Inheritance:
    A child class inherits from one parent class using class Child(Parent):.
    Example: class Dog(Animal):
  • Multiple Inheritance:
    A child class inherits from multiple parent classes using class Child(Parent1, Parent2):.
    Example: class Hybrid(Flyer, Swimmer):
  • Method Overriding:
    The child class redefines a parent’s method to provide specific behavior.
    Example: def speak(self): return "Woof!"
  • super() Function:
    Calls parent class methods from the child class.
    Example: super().__init__(args)
  • Good Practice:
    Use inheritance for clear "is-a" relationships, avoid deep inheritance hierarchies, and use super() for proper parent initialization.

Basic Example: Single Inheritance

This example shows a parent class and a child class that inherits and uses the parent’s method.



                

Example: Method Overriding

This example demonstrates a child class overriding a parent class method to provide specific behavior.



                

Example: Using super() for Parent Initialization

This example shows how to use super() to call the parent class’s constructor and extend its functionality.



                

Example: Multiple Inheritance

This example demonstrates a class inheriting from multiple parent classes, combining their functionality.



                

Example: Inheritance with Class Variables

This example shows how a child class can access and modify a parent class’s class variable.



                

Python: Polymorphism

Polymorphism in Python allows different classes to be treated as instances of a common interface or superclass, enabling methods to be used interchangeably despite different implementations. It is a core Object-Oriented Programming (OOP) concept that promotes flexibility and reusability. Polymorphism in Python is achieved through method overriding, duck typing, and operator overloading, with Python’s dynamic typing making it particularly intuitive.

  • Method Overriding:
    A child class redefines a parent class’s method to provide specific behavior.
    Example: def speak(self): return "Woof!" in a child class.
  • Duck Typing:
    Objects are treated based on their methods/attributes, not their type.
    Example: Calling speak() on objects with a speak method, regardless of their class.
  • Operator Overloading:
    Define custom behavior for operators (e.g., +) using special methods like __add__.
    Example: def __add__(self, other):
  • Method Overloading (Simulated):
    Python doesn’t support true method overloading, but default arguments or variable-length arguments can simulate it.
    Example: def add(self, a, b=0):
  • Good Practice:
    Use clear method names for polymorphic behavior, ensure consistent interfaces across classes, and avoid overly complex overloading logic.

Basic Example: Method Overriding

This example shows polymorphism through method overriding, where a child class redefines a parent class’s method.



                

Example: Duck Typing

This example demonstrates duck typing, where objects are treated polymorphically based on their methods, not their class type.



                

Example: Operator Overloading

This example shows operator overloading by defining the __add__ method to customize the + operator for a class.



                

Example: Simulated Method Overloading

This example simulates method overloading using default arguments to handle different numbers of parameters.



                

Example: Polymorphism with Inheritance and super()

This example combines polymorphism with inheritance, using super() to extend a parent’s method in a child class.



                

Python: Abstraction

Abstraction in Python is an Object-Oriented Programming (OOP) concept that hides complex implementation details and exposes only the essential features of an object. It is achieved using abstract base classes (ABCs) from the abc module, which define abstract methods that child classes must implement. Abstraction enforces a consistent interface, making code more modular and maintainable.

  • Abstract Base Class (ABC):
    Defined using the abc module by inheriting from ABC. Abstract classes cannot be instantiated directly.
    Example: class MyABC(ABC):
  • Abstract Methods:
    Declared with @abstractmethod, child classes must override these methods.
    Example: @abstractmethod def do_something(self): pass
  • Concrete Classes:
    Child classes that implement all abstract methods, making them instantiable.
    Example: class Concrete(MyABC): def do_something(self): return "Done"
  • Good Practice:
    Use abstraction for clear interfaces, keep abstract methods focused on essential behavior, and avoid complex logic in abstract classes.

Basic Example: Abstract Base Class

This example shows a simple abstract base class with an abstract method, implemented by a child class.



                

Example: Multiple Child Classes

This example demonstrates an abstract base class with multiple child classes implementing the same abstract method differently.



                

Example: Abstract Class with Concrete Method

This example shows an abstract base class with both an abstract method and a concrete method used by child classes.



                

Example: Enforcing Multiple Abstract Methods

This example demonstrates an abstract base class with multiple abstract methods that child classes must implement.



                

Example: Abstraction with Polymorphism

This example combines abstraction and polymorphism, using a list of objects to call an abstract method polymorphically.



                

Python: Encapsulation

Encapsulation in Python is an Object-Oriented Programming (OOP) concept that restricts direct access to an object’s data and methods, promoting data hiding and controlled access through public interfaces (e.g., getter and setter methods). In Python, encapsulation is achieved using naming conventions: single underscore (_variable) for protected attributes and double underscore (__variable) for private attributes with name mangling. This enhances data security and modularity.

  • Protected Attributes:
    Indicated by a single underscore (_variable), suggesting restricted access but still accessible.
    Example: self._balance = 1000
  • Private Attributes:
    Indicated by double underscores (__variable), triggering name mangling to prevent direct access.
    Example: self.__name = name
  • Getter and Setter Methods:
    Public methods to access or modify protected/private attributes safely.
    Example: def get_balance(self): return self._balance
  • Good Practice:
    Use protected/private attributes for sensitive data, provide getter/setter methods for controlled access, and avoid accessing private attributes directly outside the class.

Basic Example: Protected Attributes

This example shows a class with a protected attribute, accessed directly (though not recommended) and via a getter method.



                

Example: Private Attributes with Name Mangling

This example demonstrates a private attribute using double underscores, with getter and setter methods for controlled access.



                

Example: Getter and Setter with Validation

This example shows encapsulation with a private attribute and setter method that includes validation logic.



                

Example: Encapsulation with Inheritance

This example demonstrates encapsulation in a parent-child class hierarchy, with the child class accessing a protected attribute.



                

Example: Encapsulation with Property Decorators

This example uses property decorators to create getter and setter methods for a private attribute, providing a cleaner interface.



                

Python: Modules and Packages

In Python, a module is a single file containing Python code (e.g., functions, classes, variables) that can be imported and reused. A package is a directory containing multiple modules and an __init__.py file, enabling hierarchical organization of code. Modules and packages promote code modularity, reusability, and maintainability. Note: Due to Pyodide’s limited file system support, these examples simulate module/package behavior or use in-memory code, showing expected results in a standard Python environment.

  • Modules:
    A .py file with reusable code, imported using import module_name.
    Example: import math; print(math.sqrt(16))
  • Packages:
    A directory with an __init__.py file and modules, imported using dot notation.
    Example: from my_package import my_module
  • Importing:
    Use import, from ... import, or aliases (import module as alias) to access module/package contents.
    Example: import random as rnd
  • Good Practice:
    Use descriptive module/package names, keep __init__.py minimal, avoid circular imports, and use if __name__ == "__main__": for module-specific execution.

Basic Example: Using a Built-in Module

This example demonstrates importing and using functions from Python’s built-in math module.



                

Example: Creating and Using a Custom Module

This example simulates a custom module with functions and demonstrates importing it. In a standard Python environment, this code would be in a separate utils.py file.



                

Example: Using a Package

This example simulates a package structure with an __init__.py file and a module. In a standard Python environment, this would involve a directory with files.



                

Example: Module with if __name__ == "__main__"

This example shows a module with an if __name__ == "__main__": block to separate module code from execution logic.



                

Example: Importing Specific Functions and Aliases

This example demonstrates importing specific functions from a module and using an alias for convenience.



                

Python: Generators and Decorators

Generators and decorators are advanced Python features that enhance code efficiency and modularity. Generators are functions that yield values one at a time, creating memory-efficient iterators using the yield keyword. Decorators are functions that wrap other functions or methods to modify their behavior, often used for logging, timing, or access control. Both are powerful tools for writing clean, reusable code.

  • Generators:
    Functions that use yield to produce a sequence of values lazily.
    Example: def my_gen(): yield 1; yield 2
  • Decorators:
    Functions that wrap another function, defined with @decorator_name syntax.
    Example: @my_decorator def my_func(): pass
  • Generator Expressions:
    Similar to list comprehensions but use parentheses to create generators.
    Example: (x * 2 for x in range(5))
  • Good Practice:
    Use generators for large datasets to save memory, keep decorators simple and reusable, and document their purpose clearly.

Basic Example: Simple Generator

This example shows a basic generator function that yields a sequence of numbers.



                

Example: Generator Expression

This example demonstrates a generator expression, a concise way to create a generator without defining a function.



                

Example: Simple Decorator

This example shows a decorator that adds a message before and after a function’s execution.



                

Example: Decorator with Arguments

This example demonstrates a decorator that works with functions that take arguments, using *args and **kwargs.



                

Example: Combining Generators and Decorators

This example combines a generator with a decorator to log the values yielded by the generator.



                

Python: JSON Handling

JSON (JavaScript Object Notation) is a lightweight data format for storing and exchanging structured data. Python’s json module allows you to serialize Python objects (e.g., dictionaries, lists) to JSON strings and deserialize JSON strings back to Python objects. This is useful for APIs, configuration files, and data storage. Note: Due to Pyodide’s limited file system support, these examples use in-memory JSON operations or simulate file operations, showing expected results in a standard Python environment.

  • Serialization:
    Converting Python objects to JSON strings using json.dumps() or json.dump() (for files).
    Example: json.dumps({"name": "Alice"})
  • Deserialization:
    Converting JSON strings to Python objects using json.loads() or json.load() (for files).
    Example: json.loads('{"name": "Alice"}')
  • Error Handling:
    Use try-except to handle errors like json.JSONDecodeError for invalid JSON.
    Example: try: json.loads(data) except json.JSONDecodeError: pass
  • Good Practice:
    Validate JSON data, use indent for readable output, handle exceptions, and ensure Python data types (e.g., dict, list) are JSON-compatible.

Basic Example: Serializing and Deserializing JSON

This example demonstrates converting a Python dictionary to a JSON string and back using json.dumps() and json.loads().



                

Example: JSON with File Simulation

This example simulates writing a Python object to a JSON file and reading it back using json.dump() and json.load(). In Pyodide, we use a string to simulate file operations.



                

Example: Handling Nested JSON

This example shows how to work with nested JSON data (e.g., dictionaries within dictionaries or lists).



                

Example: Error Handling with JSON

This example demonstrates handling invalid JSON data using try-except to catch json.JSONDecodeError.



                

Example: JSON with Custom Objects

This example shows how to serialize a custom Python object to JSON by defining a custom encoding function.



                

Python: Regular Expressions (Regex)

Regular Expressions (Regex) in Python are used to match, search, and manipulate text patterns using the re module. Regex allows you to define patterns for strings (e.g., emails, phone numbers) and perform operations like searching, replacing, or splitting. It’s a powerful tool for text processing, though complex patterns require careful design to ensure accuracy.

  • Common Functions:
    Use re.search() to find the first match, re.findall() for all matches, re.sub() for replacing, and re.compile() for reusable patterns.
    Example: re.search(r"\d+", "123abc")
  • Common Patterns:
    \d (digits), \w (word characters), . (any character), * (zero or more), + (one or more), ? (optional).
    Example: r"\w+@\w+\.\w+" for emails
  • Error Handling:
    Handle invalid patterns or no matches using try-except or checking for None.
    Example: if re.search(pattern, text): pass
  • Good Practice:
    Use raw strings (r"pattern") for regex, test patterns incrementally, use re.compile() for frequently used patterns, and document complex patterns.

Basic Example: Searching for a Pattern

This example uses re.search() to find the first occurrence of a digit sequence in a string.


Example: Finding All Matches

This example uses re.findall() to extract all email addresses from a string.



                

Example: Replacing Text with Regex

This example uses re.sub() to replace all phone numbers in a string with a placeholder.



                

Example: Compiled Regex Pattern

This example demonstrates using re.compile() for a reusable regex pattern to validate dates.



                

Example: Error Handling with Regex

This example shows how to handle invalid regex patterns and unmatched patterns using try-except.



                

Python: Enums

Enumerations (Enums) in Python, provided by the enum module, allow you to define a set of named constants, making code more readable and maintainable. Enums are useful for representing fixed sets of values, such as days of the week, statuses, or categories. Each Enum member has a name and value, and Enums prevent accidental reassignment, ensuring type safety and clarity.

  • Creating Enums:
    Define an Enum by subclassing enum.Enum and listing members.
    Example: class Color(Enum): RED = 1
  • Accessing Enum Members:
    Access members using dot notation, name, or value.
    Example: Color.RED or Color['RED']
  • Enum Features:
    Iterate over members, use .name and .value, and ensure unique values with @enum.unique.
    Example: for color in Color: print(color.name)
  • Good Practice:
    Use descriptive Enum names, assign meaningful values, use Enums for fixed sets of constants, and avoid modifying Enum members after definition.

Basic Example: Defining and Using an Enum

This example shows how to define a basic Enum and access its members by name and value.



                

Example: Iterating Over Enum Members

This example demonstrates iterating over Enum members to display their names and values.



                

Example: Enum with Unique Values

This example uses @enum.unique to ensure Enum members have unique values and demonstrates comparison.



                

Example: Enum with Custom Methods

This example shows an Enum with a custom method to provide additional functionality for each member.



                

Example: Enum in a Class

This example demonstrates using an Enum within a class to represent fixed states and control behavior.



                

Python: Multithreading and Multiprocessing

Multithreading and multiprocessing in Python enable concurrent execution of tasks. Multithreading (using the threading module) runs multiple threads within the same process, ideal for I/O-bound tasks (e.g., network requests). Multiprocessing (using the multiprocessing module) runs separate processes, ideal for CPU-bound tasks (e.g., computations). Note: Pyodide has limited threading support due to browser constraints, so examples are simplified and include comments explaining standard Python behavior.

  • Multithreading:
    Threads share memory, suitable for I/O-bound tasks.
    Example: threading.Thread(target=func)
  • Multiprocessing:
    Processes have separate memory, suitable for CPU-bound tasks.
    Example: multiprocessing.Process(target=func)
  • Key Considerations:
    Use locks (threading.Lock) to avoid race conditions in threads; multiprocessing avoids Global Interpreter Lock (GIL) issues.
    Example: lock.acquire(); lock.release()
  • Good Practice:
    Use threading for I/O tasks, multiprocessing for CPU tasks, handle shared resources carefully, and test concurrency in standard Python environments due to Pyodide limitations.

Basic Example: Simple Threading

This example demonstrates creating and running two threads to print messages. In Pyodide, threading may not execute concurrently, but the code shows standard Python behavior.



                

Example: Threading with Lock

This example uses a threading.Lock to prevent race conditions when multiple threads access a shared resource.



                

Example: Simple Multiprocessing

This example demonstrates multiprocessing by running two processes to compute squares. In Pyodide, multiprocessing is limited, so the code simulates standard Python behavior.



                

Example: Multiprocessing with Shared Data

This example uses multiprocessing.Value to share data between processes safely.



                

Example: Threading with Arguments

This example shows threading with a function that accepts arguments to process a list.



                

Python: Working with APIs

Working with APIs in Python typically involves using the requests module to send HTTP requests and retrieve JSON data. APIs allow interaction with external services (e.g., weather, social media). Since Pyodide does not support requests, these examples use mock JSON data to simulate API responses, with comments explaining standard requests usage in a Python environment.

  • HTTP Requests:
    Use requests.get() to fetch data from an API endpoint.
    Example: response = requests.get("https://api.example.com/data")
  • Parsing JSON:
    Use response.json() or json.loads() to parse API responses.
    Example: data = response.json()
  • Error Handling:
    Handle HTTP errors or invalid JSON using try-except.
    Example: try: response.raise_for_status() except requests.RequestException: pass
  • Good Practice:
    Check response status codes, handle rate limits, use environment variables for API keys, and validate JSON data before processing.

Basic Example: Simulating API Response

This example simulates fetching and parsing JSON data from an API using mock data.



                

Example: Simulating Nested API Data

This example simulates parsing nested JSON data from an API response.



                

Example: Simulating API Error Handling

This example simulates handling an invalid JSON response from an API.



                

Example: Simulating API List Data

This example simulates processing a list of items from an API response.



                

Example: Simulating API with Query Parameters

This example simulates an API call with query parameters by constructing mock data.



                

Python: Unit Testing

Unit testing in Python, using the unittest module, allows you to test individual units of code (e.g., functions, methods) to ensure they work as expected. Tests are organized in test cases, using assertions to verify outputs. Unit testing improves code reliability and is essential for professional development.

  • Test Cases:
    Create test classes by subclassing unittest.TestCase and write methods starting with test_.
    Example: def test_add(self): self.assertEqual(add(2, 3), 5)
  • Assertions:
    Use methods like assertEqual, assertTrue, or assertRaises to verify results.
    Example: self.assertEqual(func(), expected)
  • Running Tests:
    Use unittest.main() to run tests or a test runner.
    Example: unittest.main(argv=[''], exit=False)
  • Good Practice:
    Write small, focused tests, cover edge cases, use descriptive test names, and run tests in isolated environments.

Basic Example: Testing a Function

This example tests a simple addition function using unittest.



                

Example: Testing Edge Cases

This example tests a function for edge cases, including zero and large numbers.



                

Example: Testing Exceptions

This example tests a function that raises an exception using assertRaises.



                

Example: Testing a Class Method

This example tests a method in a class using unittest.



                

Example: Setup and Teardown in Tests

This example uses setUp to initialize a test object and tearDown to clean up after tests.



                

Python: Logging

The logging module in Python provides a flexible framework for tracking events, debugging, and monitoring applications. Unlike print statements, logging supports different severity levels (e.g., DEBUG, INFO, ERROR), customizable output formats, and multiple output destinations (e.g., console, files). This makes it ideal for production code. Note: Since Pyodide has limited file system support, examples use in-memory streams (e.g., io.StringIO) to simulate file logging, with comments explaining standard Python file-based behavior.

  • Log Levels:
    Standard levels: DEBUG, INFO, WARNING, ERROR, CRITICAL.
    Example: logging.info("This is an info message")
  • Handlers:
    Direct logs to different outputs (e.g., console, files) using handlers like StreamHandler or FileHandler.
    Example: logging.StreamHandler()
  • Formatters:
    Customize log message formats (e.g., include timestamp, level).
    Example: logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
  • Good Practice:
    Use appropriate log levels, configure logging early, avoid excessive logging in production, and use io.StringIO for testing in Pyodide.

Basic Example: Simple Logging

This example demonstrates basic logging with different log levels to the console.



                

Example: Custom Log Format

This example customizes the log format to include timestamp and log level using a Formatter.



                

Example: Logging to In-Memory Stream

This example simulates logging to a file using io.StringIO in Pyodide (in standard Python, a FileHandler would be used).



                

Example: Logging in a Function

This example shows logging within a function to track its execution and errors.



                

Example: Multiple Handlers

This example uses multiple handlers (console and in-memory stream) to log messages to different outputs.



                

Python: Excel Handling

Python can manipulate Excel files (.xlsx) using libraries like openpyxl for reading, writing, and updating spreadsheets. This is useful for automating data analysis, reporting, and data entry tasks. Since Pyodide does not support openpyxl or file I/O, these examples simulate Excel operations using in-memory data structures (e.g., lists, dictionaries) and print results to mimic spreadsheet behavior. Comments explain how the code would work with openpyxl in a standard Python environment where an Excel file is accessed.

  • Reading Excel:
    Read data from worksheets using openpyxl.load_workbook() and access cells.
    Example: wb = openpyxl.load_workbook('data.xlsx')
  • Writing Excel:
    Create or update worksheets using openpyxl.Workbook() and save to a file.
    Example: wb.save('output.xlsx')
  • Cell Operations:
    Access or modify cells by row/column or cell reference (e.g., 'A1').
    Example: sheet['A1'] = 'Hello'
  • Good Practice:
    Validate data before writing, handle file access errors, use meaningful sheet names, and close workbooks in standard Python (not needed in Pyodide simulations).

Basic Example: Simulating Creating an Excel Sheet

This example simulates creating an Excel sheet by using a list of lists to represent rows and columns, mimicking openpyxl.Workbook().



                

Example: Simulating Reading Excel Data

This example simulates reading an Excel sheet by iterating over a list of lists, mimicking openpyxl.load_workbook().



                

Example: Simulating Updating Excel Cells

This example simulates updating a cell value in an Excel sheet by modifying a list, mimicking sheet['A1'] = value.



                

Example: Simulating Excel Data Processing

This example simulates processing Excel data by calculating the total stock, mimicking iterating over rows in openpyxl.



                

Example: Simulating Excel with Error Handling

This example simulates handling errors when accessing invalid cells, mimicking openpyxl error scenarios.



                

Python: Handling Excel with Pandas DataFrames

The pandas library in Python provides a powerful DataFrame class for manipulating tabular data, making it ideal for working with Excel files (.xlsx). DataFrames allow you to read, write, filter, and analyze Excel data efficiently, similar to working with spreadsheets. Since Pyodide does not support pandas or file I/O, these examples simulate DataFrame operations using lists and dictionaries to represent Excel data, with comments explaining how the code would work with pandas in a standard Python environment (e.g., using pd.read_excel and to_excel). In a real environment, you would need pandas and openpyxl or xlrd installed for Excel file handling.

  • Reading Excel:
    Use pd.read_excel() to load an Excel file into a DataFrame.
    Example: df = pd.read_excel('data.xlsx')
  • Writing Excel:
    Save a DataFrame to an Excel file using df.to_excel().
    Example: df.to_excel('output.xlsx', index=False)
  • DataFrame Operations:
    Manipulate data using DataFrame methods like filtering, grouping, or updating values.
    Example: df['column'] = df['column'] * 2
  • Good Practice:
    Validate data types, handle missing values, use descriptive column names, and catch file access errors with try-except in standard Python.

Basic Example: Simulating Creating a DataFrame

This example simulates creating a pandas DataFrame using a dictionary and printing it to mimic an Excel sheet.



                

Example: Simulating Reading Excel into a DataFrame

This example simulates reading an Excel file into a DataFrame using a list of dictionaries to represent rows.



                

Example: Simulating Updating a DataFrame

This example simulates updating a DataFrame column by modifying a dictionary, mimicking df['column'] = value.



                

Example: Simulating DataFrame Filtering

This example simulates filtering a DataFrame to select rows based on a condition, mimicking df[df['column'] > value].



                

Example: Simulating DataFrame Aggregation

This example simulates aggregating DataFrame data by calculating the average price, mimicking df['column'].mean().



                

Python: Pandas for Excel and CSV Data Manipulation

The pandas library in Python is ideal for reading, transforming, and writing tabular data in Excel (.xlsx) and CSV (.csv) files using DataFrame objects. This tutorial demonstrates how to read specific fields from Excel or CSV files, rename columns, apply transformations (e.g., filtering, adding calculated columns), and save results to a new file. Examples use mock data to represent file-based operations, but include code for actual file handling with pd.read_excel, pd.read_csv, df.to_excel, and df.to_csv, assuming pandas and openpyxl are installed in a standard Python environment.

  • Reading Data:
    Use pd.read_excel() or pd.read_csv() with usecols to read specific columns.
    Example: df = pd.read_excel('data.xlsx', usecols=['Name', 'Age'])
  • Transformations:
    Rename columns with df.rename(), filter rows with df[df['column'] > value], or add calculated columns.
    Example: df['NewColumn'] = df['OldColumn'] * 2
  • Writing Data:
    Save DataFrames to Excel or CSV using df.to_excel() or df.to_csv().
    Example: df.to_csv('output.csv', index=False)
  • Good Practice:
    Validate input data, handle missing values with df.dropna() or df.fillna(), use descriptive column names, and catch file access errors with try-except.

Example 1: Reading Specific Columns from CSV and Renaming

This example reads specific columns from a CSV file, renames them, and saves to a new CSV.



                

Example 2: Reading Excel and Filtering Rows

This example reads an Excel file, filters rows based on a condition, and saves to a new Excel file.



                

Example 3: Adding a Calculated Column and Saving to CSV

This example reads a CSV, adds a calculated column, and saves to a new CSV.



                

Example 4: Handling Missing Data and Renaming Columns

This example reads an Excel file with missing data, fills missing values, renames columns, and saves to a new Excel.



                

Example 5: Grouping and Aggregating Data

This example reads a CSV, groups data by a column, calculates aggregates, and saves to a new CSV.



                

Python: Enumerate, Eval, Timer Decorator, and Dictionary Key Iteration

This tutorial covers four Python concepts: enumerate for iterating with indices, eval for evaluating string expressions, a timer decorator for measuring function execution time, and dictionary key iteration using for key in list(dict1). These tools are useful for iteration, dynamic code execution, performance monitoring, and dictionary manipulation. All examples are Pyodide-compatible, using in-memory operations to ensure execution in a browser environment.

  • Enumerate:
    Provides index and value during iteration over a sequence.
    Example: for index, value in enumerate(['a', 'b']): print(index, value)
  • Eval:
    Evaluates a string as a Python expression, returning the result.
    Example: result = eval('2 + 3')
  • Timer Decorator:
    Measures a function’s execution time using a decorator, often with time.time().
    Example: @timer\ndef my_function(): pass
  • Dictionary Key Iteration:
    Iterates over dictionary keys using list(dict1) to create a list of keys.
    Example: for key in list(dict1): print(key, dict1[key])
  • Good Practice:
    Use enumerate for indexed loops, avoid eval with untrusted input, log timer results, and use dictionary methods like .keys() instead of list(dict1) for efficiency unless modifying the dictionary during iteration.

Example 1: Using Enumerate for Indexed Iteration

This example uses enumerate to iterate over a list with indices and values.



                

Example 2: Using Eval for Dynamic Expression Evaluation

This example uses eval to evaluate a string expression, with error handling for safety.



                

Example 3: Timer Decorator for Function Timing

This example defines a timer decorator to measure the execution time of a function.



                

Example 4: Dictionary Key Iteration with list(dict1)

This example iterates over dictionary keys using list(dict1) to access key-value pairs.



                

Example 5: Combining Enumerate, Eval, and Timer with Dictionary

This example combines enumerate, eval, a timer decorator, and dictionary iteration to process a list of expressions stored in a dictionary.



                

Python: for i in list1 vs for i in list1[:]

In Python, iterating over a list using for i in list1 accesses the list directly, while for i in list1[:] iterates over a shallow copy of the list. The key difference arises when modifying the list during iteration: direct iteration may lead to unexpected behavior (e.g., skipped elements), while iterating over a copy ensures the original list’s structure is preserved during the loop. This tutorial explains both approaches, their use cases, and best practices, with Pyodide-compatible examples using in-memory operations.

  • for i in list1:
    Iterates directly over the list’s elements, efficient but risky if modifying the list (e.g., removing items).
    Example: for i in list1: list1.remove(i) may skip elements.
  • for i in list1[:]:
    Iterates over a shallow copy of the list, safer for modifications as the original list is unaffected during iteration.
    Example: for i in list1[:]: list1.remove(i) processes all elements.
  • Key Considerations:
    Direct iteration is memory-efficient but can cause issues with dynamic list changes. Copy iteration uses more memory but is safer for modifications.
    Example: Use list1[:] when removing items, direct iteration for read-only operations.
  • Good Practice:
    Use direct iteration for simple loops, list1[:] for modifications, avoid modifying lists unnecessarily, and consider list comprehensions or other methods for complex operations.

Example 1: Basic Direct Iteration with for i in list1

This example uses for i in list1 to iterate over a list and print elements, demonstrating simple read-only iteration.



                

Example 2: Direct Iteration with Modification (Issue)

This example shows how modifying a list during direct iteration with for i in list1 can skip elements.



                

Example 3: Iteration with Copy Using for i in list1[:]

This example uses for i in list1[:] to safely modify the original list by iterating over a copy.



                

Example 4: Combining Enumerate with list1[:] for Safe Modification

This example combines enumerate with list1[:] to track indices while safely modifying the list.



                

Example 5: Comparing Performance with Timer Decorator

This example uses a timer decorator to compare the performance of for i in list1 vs for i in list1[:] for a large list.



                
Owner: KOTHA ABHISHEK