Introduction to Use Python

This guide provides an introduction to using Python, a versatile and powerful programming language. Whether you’re a beginner or looking to enhance your skills, this guide will help you get started with Python.

Working Directory

The term “working directory” is frequently employed within the context of Python programming. Specifically, it pertains to the directory from which a Python script, data or interactive session is currently executing. In essence, the working directory represents the present location of a Python program within the file system of a computer. Notably, Python automatically searches the working directory for files in the event that a user does not specify a full path to a file. This is a useful feature that streamlines the process of accessing files within a specific location. By leveraging the working directory, programmers can easily organize and access files without the need to enter a full path each time they wish to do so.

You can get the current working directory using the os module:

Code
import os

current_directory = os.getcwd()
print("Current working directory:", current_directory)

Example output:

Current working directory: /home/zia07/Dropbox/Python_Website/Python_Beginner

If you want to change the working directory, you can use os.chdir():

Code
import os
path = "/home/zia207/WebSites/Python_Website/Python_for_Beginners/Data/"
os.chdir(path)
print("Current Working Directory ", os.getcwd())

Example output:

Current Working Directory  /home/zia07/Dropbox/Python_Website/Python_Beginner/Data

Basic Mathematical Operators

Python allows you to perform various mathematical operations using basic mathematical operators.

Here’s an example of how you can use these operators in Python:

Code
# Addition
5 + 3  # output: 8
Code
# Subtraction
10 - 4  # output: 6
Code
# Multiplication
6 * 2  # output: 12
Code
# Division
20 / 5  # output: 4.0
Code
# Floor Division (returns the integer part of the division)
20 // 6  # output: 3
Code
# Modulus (returns the remainder of the division)
20 % 6  # output: 2
Code
# Exponentiation
2 ** 3  # output: 8

Assigning Values to Variables

In Python, as in algebra, it is common to assign a computation to a variable name. This allows us to refer to the result of the computation later in our code. To assign a result to a variable, we use the = symbol.

Code
# Assigning a value to a variable
x = 5

# You can also assign the result of an expression to a variable
y = 3 + 4

# Variables can hold different types of data
name = "John"
age = 25
is_student = True

# You can also assign the value of one variable to another
a = 10
b = a  # Now b has the same value as a

# Variables can be reassigned with new values
x = 10
x = x + 1  
print(x)  # output: 11

Built-in Functions

Python comes with a rich set of built-in functions that are readily available for you to use without needing to import any additional modules. Here are some important built-in functions in Python:

Code
print("Hello, world!")  # output: Hello, world!
Code
length = len("Hello")  
print(length)  # output: 5
Code
t = type(5)  
t  # output: int
Code
numbers = list(range(1, 6)) 
numbers  # output: [1, 2, 3, 4, 5]
Code
total = sum([1, 2, 3, 4, 5])  
total  # output: 15
Code
max([3, 1, 4, 1, 5])  # output: 5
min([3, 1, 4, 1, 5])  # output: 1
Code
abs(-10)  # output: 10
Code
round(3.14159, 2)  # output: 3.14
Code
sorted([3, 1, 4, 1, 5])  # output: [1, 1, 3, 4, 5]

Pre-built Modules

Python includes a wide range of pre-built modules that serve various purposes. These modules offer a broad spectrum of functionalities such as file I/O, regular expression processing, network programming, web services, image processing, and many more. The built-in modules in Python provide an extensive and robust foundation for software development, which makes it a popular choice among developers.

Here’s a list of some commonly used built-in modules in Python:

  • os: Provides a portable way of using operating system-dependent functionality.
  • sys: Provides access to some variables used or maintained by the Python interpreter and to functions that interact with the interpreter.
  • math: Provides mathematical functions defined by the C standard.
  • random: Implements pseudo-random number generators for various distributions.
  • datetime: Supplies classes for manipulating dates and times.
  • json: Encodes and decodes JSON data.
  • csv: Provides classes for reading and writing tabular data in CSV format.
  • re: Provides support for regular expressions (regex).
  • collections: Provides additional data structures like OrderedDict, defaultdict, Counter, etc.
  • pickle: Implements binary protocols for serializing and de-serializing Python objects.
  • subprocess: Allows you to spawn new processes, connect to their input/output/error pipes, and obtain their return codes.
  • argparse: Helps in parsing command-line arguments.
  • logging: Provides a flexible framework for emitting log messages from Python programs.
  • socket: Provides access to the BSD socket interface.
  • requests: Simplifies making HTTP requests.
  • sqlite3: Provides a lightweight database engine in Python standard library.
  • unittest: A unit testing framework.
  • time: Provides various time-related functions.
  • multiprocessing: Provides support for concurrent execution using processes.
  • threading: Provides support for working with threads.
  • io: Provides classes for working with streams of data.
  • gzip: Provides functions for working with gzip compressed files.

Math Module

The Python math module is a powerful package that comes with a wide range of functions and constants specifically designed for mathematical operations.

Code
import math

# Trigonometric functions
angle_radians = math.radians(45)
print("sin(45°) =", math.sin(angle_radians))  
print("cos(45°) =", math.cos(angle_radians))  
print("tan(45°) =", math.tan(angle_radians))  

# Exponential and logarithmic functions
print("e^2 =", math.exp(2))   
print("log(10) =", math.log(10))   
print("log10(100) =", math.log10(100))  
print("sqrt(25) =", math.sqrt(25))  

# Constants
print("pi =", math.pi)   
print("e =", math.e)    

# Ceiling and floor functions
print("ceil(3.14) =", math.ceil(3.14))   
print("floor(3.14) =", math.floor(3.14)) 

# Factorial
print("Factorial of 5 =", math.factorial(5))  

# Absolute value
print("Absolute value of -5.5 =", math.fabs(-5.5))

Datetime Module

Code
from datetime import datetime

# Get the current date and time
current_datetime = datetime.now()
print("Current date and time:", current_datetime)

# Format a datetime object as a string
formatted_datetime = current_datetime.strftime("%Y-%m-%d %H:%M:%S")
print("Formatted datetime:", formatted_datetime)

Example output:

Current date and time: 2024-02-22 23:39:15.073010
Formatted datetime: 2024-02-22 23:39:15

Basic Data Types

In Python, data types represent the type of value a variable can hold. Here are some of the basic data types in Python:

  • Numeric Types:
    • int: Integer type, e.g., 5, -3, 1000.
    • float: Floating-point type, e.g., 3.14, -0.001, 2.0.
  • Boolean Type:
    • bool: Represents boolean values True and False.
  • Sequence Types:
    • str: String type, e.g., “hello”, ‘world’.
    • list: Ordered collection of items, e.g., [1, 2, 3], [‘apple’, ‘banana’, ‘orange’].
    • tuple: Ordered collection of items (immutable), e.g., (1, 2, 3), (‘a’, ‘b’, ‘c’).
  • Mapping Type:
    • dict: Collection of key-value pairs, e.g., {‘name’: ‘Alice’, ‘age’: 30}.
  • Set Types:
    • set: Unordered collection of unique items, e.g., {1, 2, 3}, {‘apple’, ‘banana’, ‘orange’}.
    • frozenset: Immutable version of set.
  • None Type:
    • None: Represents the absence of a value or a null value.
Code
# Numeric Types
integer_num = 5
float_num = 3.14

# Boolean Type
is_true = True
is_false = False

# Sequence Types
string_var = "hello"
list_var = [1, 2, 3, 4, 5]
tuple_var = ('a', 'b', 'c', 12, 0.5)

# Mapping Type
dictionary_var = {'name': 'Alice', 'age': 30}

# Set Types
set_var = {1, 2, 3, 4}
frozenset_var = frozenset({1, 2, 3})

# None Type
none_var = None

# Printing the variables
print("Integer:", integer_num)
print("Float:", float_num)
print("Boolean (True):", is_true)
print("Boolean (False):", is_false)
print("String:", string_var)
print("List:", list_var)
print("Tuple:", tuple_var)
print("Dictionary:", dictionary_var)
print("Set:", set_var)
print("Frozen Set:", frozenset_var)
print("None:", none_var)

Accessing Tuple Items

Tuples are ordered collections of elements, similar to lists, but they are immutable. You can access tuple items using indexing or slicing.

Code
my_tuple = ('apple', 'banana', 'cherry')

# Access the first item
first_item = my_tuple[0]
print(first_item)  # Output: 'apple'

# Access the second item
second_item = my_tuple[1]
print(second_item)  # Output: 'banana'

# Access the last item using negative indexing
last_item = my_tuple[-1]
print(last_item)  # Output: 'cherry'
Code
my_tuple = ('apple', 'banana', 'cherry', 'date', 'elderberry')

# Get items from index 1 to 3 (excluding 3)
subset = my_tuple[1:3]
print(subset)  # Output: ('banana', 'cherry')

# Get all items from index 2 to the end
subset = my_tuple[2:]
print(subset)  # Output: ('cherry', 'date', 'elderberry')

# Get all items from the beginning to index 3 (excluding 3)
subset = my_tuple[:3]
print(subset)  # Output: ('apple', 'banana', 'cherry')

Updating Tuples

Tuples are immutable, so you can’t change them directly. But you can create a new tuple by concatenation or comprehension.

Code
# Concatenating Tuples
my_tuple = ('apple', 'banana', 'cherry')
updated_tuple = my_tuple[:2] + ('orange',) + my_tuple[2:]
print(updated_tuple)  # output: ('apple', 'banana', 'orange', 'cherry')
Code
# Tuple Comprehension
my_tuple = ('apple', 'banana', 'cherry')
updated_tuple = tuple('orange' if item == 'banana' else item for item in my_tuple)
print(updated_tuple)  # output: ('apple', 'orange', 'cherry')

Joining Tuples

Code
tuple1 = ('a', 'b', 'c')
tuple2 = (1, 2, 3)

joined_tuple = tuple1 + tuple2
print(joined_tuple)  # output: ('a', 'b', 'c', 1, 2, 3)

Finding Index in Tuple

Code
my_tuple = ('apple', 'banana', 'cherry', 'banana')

# Find the index of 'banana'
index = my_tuple.index('banana')
print("Index of 'banana':", index)  # Output: 1
Code
# Handle missing item
try:
    index = my_tuple.index('orange')
    print("Index of 'orange':", index)
except ValueError:
    print("'orange' not found in the tuple")  # output: 'orange' not found in the tuple

List

Lists are ordered collections of items that can be changed (mutable). You can create a list using square brackets [] and separate items with commas. A list is a mutable, ordered collection of items (elements) that can hold elements of different data types (integers, strings, floats, other lists, etc.). Lists are one of the most commonly used data structures in Python because they are flexible and dynamic — you can add, remove, or change elements after the list is created.

Lists are defined using square brackets [], with elements separated by commas.

Code
# Example 1: List of integers
numbers = [1, 2, 3, 4, 5]

# Example 2: List of strings
fruits = ["apple", "banana", "cherry"]

# Example 3: Mixed data types
mixed = [1, "hello", 3.14, True, [1, 2, 3]]  # includes int, str, float, bool, and another list!

# Example 4: Empty list
empty_list = []

# Example 5: Nested list
matrix = [[1, 2, 3],
          [4, 5, 6],
          [7, 8, 9]]
Code
fruits = ["apple", "banana", "cherry"]

# Accessing elements
print(fruits[0])        # Output: "apple"

# Modifying elements
fruits[1] = "blueberry"
print(fruits)           # Output: ['apple', 'blueberry', 'cherry']

# Adding elements
fruits.append("orange")
print(fruits)           # Output: ['apple', 'blueberry', 'cherry', 'orange']

# Removing elements
fruits.remove("apple")
print(fruits)           # Output: ['blueberry', 'cherry', 'orange']

# Length of list
print(len(fruits))      # Output: 3

Modifying Lists

You can modify lists by adding, removing, or changing elements. Here are some common operations to modify lists: - Adding Elements: - append(): Adds an element to the end of the list. - insert(): Inserts an element at a specified index. - extend(): Adds elements from another list (or any iterable) to the end of the list. - Removing Elements: - remove(): Removes the first occurrence of a specified value. - pop(): Removes and returns an element at a specified index (or the last element if no index is specified). - clear(): Removes all elements from the list. - Changing Elements: - You can change the value of an element by accessing it via its index and assigning a new value. Example:

Code
# Initial list
fruits = ["apple", "banana", "cherry"]
print("Original list:", fruits)
# Output: Original list: ['apple', 'banana', 'cherry']

print("\n" + "="*40 + "\n")

# ================================
# ADDING ELEMENTS
# ================================

# 1. append() - adds to the END
fruits.append("orange")
print("After append('orange'):", fruits)
# Output: ['apple', 'banana', 'cherry', 'orange']

# 2. insert() - inserts at SPECIFIED INDEX
fruits.insert(1, "blueberry")  # insert at index 1
print("After insert(1, 'blueberry'):", fruits)
# Output: ['apple', 'blueberry', 'banana', 'cherry', 'orange']

# 3. extend() - adds MULTIPLE elements from another iterable
more_fruits = ["mango", "kiwi"]
fruits.extend(more_fruits)
print("After extend(['mango', 'kiwi']):", fruits)
# Output: ['apple', 'blueberry', 'banana', 'cherry', 'orange', 'mango', 'kiwi']

print("\n" + "="*40 + "\n")

# ================================
# REMOVING ELEMENTS
# ================================

# 1. remove() - removes FIRST OCCURRENCE of a value
fruits.remove("banana")
print("After remove('banana'):", fruits)
# Output: ['apple', 'blueberry', 'cherry', 'orange', 'mango', 'kiwi']

# 2. pop() - removes and RETURNS element at given index (default: last)
popped = fruits.pop()  # removes last item
print("After pop() - removed:", popped)
print("List now:", fruits)
# Output: removed: kiwi
#         List now: ['apple', 'blueberry', 'cherry', 'orange', 'mango']

popped_index = fruits.pop(1)  # removes item at index 1
print("After pop(1) - removed:", popped_index)
print("List now:", fruits)
# Output: removed: blueberry
#         List now: ['apple', 'cherry', 'orange', 'mango']

# 3. clear() - removes ALL elements
# Let's make a copy first to preserve data
temp_fruits = fruits.copy()
temp_fruits.clear()
print("After clear():", temp_fruits)
# Output: []

print("\n" + "="*40 + "\n")

# ================================
# CHANGING ELEMENTS
# ================================

# Change value by index assignment
fruits[0] = "strawberry"      # change first element
fruits[-1] = "pineapple"      # change last element
print("After changing elements:", fruits)
# Output: ['strawberry', 'cherry', 'orange', 'pineapple']

# You can also replace a slice
fruits[1:3] = ["grape", "watermelon"]  # replace index 1 and 2
print("After slice assignment:", fruits)
# Output: ['strawberry', 'grape', 'watermelon', 'pineapple']

print("\n" + "="*40 + "\n")

# Final list
print("Final list:", fruits)
# Output: ['strawberry', 'grape', 'watermelon', 'pineapple']

Control Flow

Control statements allow you to control the execution flow of your program — conditionals (if, else), loops (for, while), etc.

Major types: - if: conditional programming - if..else: conditional programming - for: iterate over fixed number of items - while: loop until condition is False

Code
print("=== CONTROL FLOW EXAMPLES ===\n")

# =============================================
#  iif Statement — Conditional Programming
# =============================================
print("🔹 1. 'if' Statement:")

temperature = 30

if temperature > 25:
    print("It's a hot day!")

# Output: It's a hot day!

print("\n" + "-"*40 + "\n")

# =============================================
#  if..else Statement — Conditional Programming
# =============================================
print("🔹 2. 'if..else' Statement:")

temperature = 20

if temperature > 25:
    print("It's a hot day!")
else:
    print("It's not too hot today.")

# Output: It's not too hot today.

print("\n" + "-"*40 + "\n")

# =============================================
#  if..elif..else — Multiple Conditions
# =============================================
print("🔹 3. 'if..elif..else' Statement (Bonus!):")

score = 85

if score >= 90:
    grade = "A"
elif score >= 80:
    grade = "B"
elif score >= 70:
    grade = "C"
else:
    grade = "F"

print(f"Score: {score} → Grade: {grade}")
# Output: Score: 85 → Grade: B

print("\n" + "-"*40 + "\n")

# =============================================
#  for Loop — Iterate Over Fixed Items
# =============================================
print("🔹 4. 'for' Loop:")

fruits = ["apple", "banana", "cherry"]

print("Fruits in my basket:")
for fruit in fruits:
    print(f" - {fruit}")

# Output:
# Fruits in my basket:
#  - apple
#  - banana
#  - cherry

print()

# Using range()
print("Counting from 1 to 5:")
for i in range(1, 6):  # range(1,6) = 1,2,3,4,5
    print(i, end=" ")
print()

# Output: 1 2 3 4 5

print("\n" + "-"*40 + "\n")

# =============================================
#  while Loop — Loop Until Condition is False
# =============================================
print("🔹 5. 'while' Loop:")

count = 3

print("Blastoff countdown:")
while count > 0:
    print(count)
    count -= 1  # same as count = count - 1
print("Blastoff! 🚀")

# Output:
# Blastoff countdown:
# 3
# 2
# 1
# Blastoff! 🚀

print("\n" + "-"*40 + "\n")

# =============================================
# while with break and continue
# =============================================
print("🔹 Bonus: 'while' with break and continue")

x = 0
print("Skipping 3, stopping at 6:")
while x < 10:
    x += 1
    if x == 3:
        continue  # skip printing 3
    if x == 6:
        break     # stop loop when x is 6
    print(x, end=" ")
print()

# Output: 1 2 4 5

print("\n" + "="*40)

Functions in Python

Functions are reusable blocks of code. Defined with def, can take parameters and return values.

Code
def add_numbers(x, y):
    sum = x + y
    return sum

add_numbers(2,4)  # output: 6
Code
result = add_numbers(3, 5)
print(result)  # Output: 8
Code
def greet():
    print("Hello, welcome!")

greet()  # Output: Hello, welcome!
Code
def fulll_name(last_name):
    return "Zia " + last_name

fulll_name("Ahmed")  # output: 'Zia Ahmed'

Nested Functions

Code
def y():
    r = 2
    n = 5
    def z():
        return (1+r)**n
    x = 10
    return x/z()

y()  # output: 0.0411522633744856

Returning Multiple Outputs

Code
def results_all(x, y):
    results1 = 2*x + y
    results2 = x + 2*y
    results3 = 2*x + 2*y
    results4 = x/y
    return [results1, results2, results3, results4]

results_all(1, 2)  # output: [4, 5, 6, 0.5]

Row-wise Mean Function (Pandas)

Code
!pip install pandas numpy
Code
import pandas as pd
import numpy as np
Code
def calculate_row_mean(df):
    """
    Calculate the row mean of a DataFrame.

    Parameters:
    df (pandas.DataFrame): Input DataFrame.

    Returns:
    pandas.Series: Row means.
    """
    row_means = df.mean(axis=1)
    return row_means

# Create the dataframe
df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6], 'C': [7, 8, 9]})
# Calculate row mean
calculate_row_mean(df) 

Column-wise Mean Function

Code
import pandas as pd

def calculate_column_mean(df):
    """
    Calculate the column mean of a DataFrame.

    Parameters:
    df (pandas.DataFrame): Input DataFrame.

    Returns:
    pandas.Series: Column means.
    """
    column_means = df.mean()
    return column_means

df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6], 'C': [7, 8, 9]})
column_means = calculate_column_mean(df)
print(column_means)  # output: A    2.0
                     #         B    5.0
                     #         C    8.0
                     #         dtype: float64

Temperature Conversion Function

Code
def C_to_F(C):
    f = (9/5) * C + 32
    return f

C_to_F(10)  # output: 50.0
Code
C = list(range(4, 11))
f_values = [C_to_F(c) for c in C]
f_values  # output: [39.2, 41.0, 42.8, 44.6, 46.4, 48.2, 50.0]

Half-Life Calculation Function

Code
import math

def calculate_half_life(decay_constant):
    """
    Calculate the half-life of a substance given the decay constant.

    Parameters:
    decay_constant (float): The decay constant of the substance.

    Returns:
    float: The half-life of the substance.
    """
    half_life = math.log(2) / decay_constant
    return half_life

# Example usage:
decay_constant = 0.1  # Example decay constant
half_life = calculate_half_life(decay_constant)
print("Half-life:", half_life)  # output: Half-life: 6.931471805599452

Lambda Function

A lambda function is a small anonymous function defined using the lambda keyword. It can take any number of arguments but can only have one expression. Lambda functions are often used for short, throwaway functions that are not reused elsewhere in the code (like in map(), filter(), sorted(), etc.).

lambda arguments: expression

Simple Lambda — Add Two Numbers

Code
add = lambda x, y: x + y
print(add(3, 5))  # Output: 8

same as:

Code
def add(x, y):
    return x + y

Square a Number

Code
square = lambda x: x ** 2
print(square(4))  

With map() — Apply function to every item

Code
numbers = [1, 2, 3, 4]
squared = list(map(lambda x: x**2, numbers))
print(squared)  

With sorted() — Custom sort order

Code
names = ["Alice", "Bob", "Charlie"]
sorted_by_length = sorted(names, key=lambda name: len(name))
print(sorted_by_length)  # Output: ['Bob', 'Alice', 'Charlie']

Classes and Objects

Classes are blueprints for creating objects. They encapsulate data and behavior. Objects are instances of classes and can have attributes (data) and methods (functions) associated with them. In following example, we define a simple class Dog with attributes name and age, and a method bark() that prints a message. Objects dog1 and dog2 are created from the Dog class, and their attributes and methods are accessed.

  • class Dog = blueprint for dogs.
  • __init__ = setup when dog is born (give it a name & age).
  • self = refers to this specific dog.
  • bark() = what the dog can do.
  • my_dog = actual dog created from the blueprint.
Code
### Example: Defining a Simple Class
class Dog:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def bark(self):
        return "Woof!"

# Creating an instance (object) of the Dog class
my_dog = Dog("Buddy", 3)

# Accessing attributes
print(my_dog.name)  # Output: Buddy
print(my_dog.age)   # Output: 3

# Calling a method
print(my_dog.bark())  # Output: Woof!

Dunder Methods

Dunder methods (short for “double underscore” methods) are special methods in Python that have double underscores at the beginning and end of their names. They are also known as magic methods or special methods. Dunder methods allow you to define how objects of a class behave with respect to built-in operations and functions.

By defining dunder methods, you can:

  • Make your objects printable in a nice way (print(obj))
  • Add two objects together (obj1 + obj2)
  • Compare objects (obj1 > obj2)
  • Make objects iterable (for item in obj)
  • Use your object like a list or dictionary (obj[key])
  • And much more!

Some common dunder methods include:

  • __init__(self, ...): Called when an object is created. Used for initializing attributes.
  • __str__(self): Called by the print() function and str() to get a string representation of the object.
  • __repr__(self): Called by the repr() function to get an “official” string representation of the object.
  • __len__(self): Called by the len() function to get the length of the object.
  • __getitem__(self, key): Called to get an item from a collection using square brackets (e.g., obj[key]).
  • __setitem__(self, key, value): Called to set an item in a collection using square brackets (e.g., obj[key] = value).
  • __delitem__(self, key): Called to delete an item from a collection using square brackets (e.g., del obj[key]).
  • __add__(self, other): Called to add two objects using the + operator.
  • __sub__(self, other): Called to subtract two objects using the - operator.
  • __eq__(self, other): Called to compare two objects for equality using the == operator.
  • __lt__(self, other): Called to compare two objects for less-than using the < operator.

By implementing these methods, you can make your custom classes work seamlessly with Python’s built-in features and syntax.

Code
class CustomList:
    def __init__(self, items=None):
        """Initialize the list. Called when object is created."""
        self.items = items if items is not None else []

    def __str__(self):
        """Called by print() and str(). Returns user-friendly string."""
        return f"CustomList({self.items})"

    def __repr__(self):
        """Called by repr(). Returns 'official' string (ideally recreatable)."""
        return f"CustomList({self.items!r})"

    def __len__(self):
        """Called by len(). Returns number of items."""
        return len(self.items)

    def __getitem__(self, key):
        """Called for obj[key]. Get item at index or slice."""
        return self.items[key]

    def __setitem__(self, key, value):
        """Called for obj[key] = value. Set item at index or slice."""
        self.items[key] = value

    def __delitem__(self, key):
        """Called for del obj[key]. Delete item at index or slice."""
        del self.items[key]

    def __add__(self, other):
        """Called for obj1 + obj2. Concatenate two CustomLists."""
        if isinstance(other, CustomList):
            return CustomList(self.items + other.items)
        else:
            raise TypeError("Can only add another CustomList")

    def __sub__(self, other):
        """Called for obj1 - obj2. Remove elements in other from self."""
        if isinstance(other, CustomList):
            result = [item for item in self.items if item not in other.items]
            return CustomList(result)
        else:
            raise TypeError("Can only subtract another CustomList")

    def __eq__(self, other):
        """Called for obj1 == obj2. Check if items are equal."""
        if isinstance(other, CustomList):
            return self.items == other.items
        return False

    def __lt__(self, other):
        """Called for obj1 < obj2. Compare by length."""
        if isinstance(other, CustomList):
            return len(self) < len(other)
        return NotImplemented

Using the CustomList Class

Code
# =============================================================
# DEMO: Using the CustomList Class
# =============================================================

print("=== Creating and Initializing ===")
cl1 = CustomList([1, 2, 3])      # __init__
cl2 = CustomList([4, 5])

print(cl1)                       # __str__ → CustomList([1, 2, 3])
print(repr(cl1))                 # __repr__ → CustomList([1, 2, 3])

print("\n=== Length ===")
print(len(cl1))                  # __len__ → 3

print("\n=== Indexing ===")
print(cl1[0])                    # __getitem__ → 1
cl1[0] = 99                      # __setitem__
print(cl1)                       # → CustomList([99, 2, 3])
del cl1[0]                       # __delitem__
print(cl1)                       # → CustomList([2, 3])

print("\n=== Addition & Subtraction ===")
cl3 = cl1 + cl2                  # __add__
print("cl1 + cl2 =", cl3)        # → CustomList([2, 3, 4, 5])

cl4 = CustomList([2, 4])
cl5 = cl3 - cl4                  # __sub__
print("cl3 - cl4 =", cl5)        # → CustomList([3, 5])  (removed 2 and 4)

print("\n=== Comparison ===")
print("cl1 == CustomList([2, 3]) →", cl1 == CustomList([2, 3]))  # __eq__ → True
print("cl1 < cl3 →", cl1 < cl3)  # __lt__ → True (2 < 4)

print("\n=== Edge Case: Invalid Operations ===")
try:
    result = cl1 + "not a list"
except TypeError as e:
    print("Error:", e)           # → Error: Can only add another CustomList

Dunder Method Quick Reference

Method Triggered By Purpose
__init__ CustomList([1,2,3]) Initialize object
__str__ print(obj) User-friendly string
__repr__ repr(obj) Developer-friendly / recreatable string
__len__ len(obj) Return “length” of object
__getitem__ obj[key] Get item by index or key
__setitem__ obj[key] = value Set item at index or key
__delitem__ del obj[key] Delete item at index or key
__add__ obj1 + obj2 Define addition behavior
__sub__ obj1 - obj2 Define subtraction behavior
__eq__ obj1 == obj2 Define equality
__lt__ obj1 < obj2 Define “less than” comparison

main

__main__ is the name of the environment where top-level Python code is run — “the main program”.

When you run a Python script directly, Python sets the special variable name to “main”.

Code
if __name__ == "__main__":
    # This code only runs if you execute THIS file directly
    print("Hello from main!")

Let’s say you have a file called greet.py:

Code
# greet.py
def say_hello(name):
    return f"Hello, {name}!"

# This block only runs if you RUN this file directly
if __name__ == "__main__":
    print(say_hello("Alice"))
Code
 !python greet.py

The if name == “main”: block runs.

Code
import greet

print(greet.say_hello("Bob"))

Summary and Conclusion

This guide provided an introduction to using Python, covering essential topics such as working directories, basic mathematical operators, variable assignment, built-in functions, pre-built modules, data types, control flow, functions, lambda functions, classes and objects, and dunder methods. By understanding these fundamental concepts, you can start writing Python code effectively and explore more advanced topics in the future. Happy coding!

Resources

  1. Python.org — Official Tutorial

  2. Automate the Boring Stuff with Python — Free Online Book + Videos

  3. Real Python — Tutorials

  4. W3Schools Python Tutorial

  5. freeCodeCamp — Learn Python — Full Course for Beginners (YouTube)

  6. Google’s Python Class

Interactive Learning Platforms

  1. Codecademy — Learn Python 3

  2. DataCamp — Intro to Python

  3. SoloLearn — Python Course (Mobile App + Web)

Practice & Challenges

  1. Exercism — Python Track

  2. Edabit — Python Challenges

  3. Codewars — Python Katas

Tools & Setup for Beginners

1 Install Python: python.org/downloads

  1. Use an IDE or Editor:
  1. Online Python Editors (No Install Needed):

YouTube Channels

  1. Corey Schafer
  1. CS Dojo / YK Sugi
  1. freeCodeCamp.org
  • Full-length courses (4–12 hours) — great for deep dives.

Communities for Help

  • Reddit: r/learnpython — friendly, active, beginner-focused.
  • Stack Overflow: Ask specific coding questions.
  • Discord: Python Discord server — live chat with learners and pros.
  • Python Discord Invite: https://discord.gg/python

Quick Start Roadmap for Beginners

  1. Install Python + Thonny or VS Code
  2. Learn: variables, data types, input/output, conditionals, loops
  3. Practice: small programs (calculator, to-do list, quiz)
  4. Learn: functions, lists, dictionaries
  5. Learn: file handling, error handling
  6. Learn: OOP basics (classes, objects)
  7. Build a project! (e.g., number guessing game, contact book, web scraper)