Skip to content

Repository files navigation

📘 Utrains :- Python Fundamentals Course

📌 Course Overview

This course covers the fundamentals of Python programming, starting from basic syntax to file handling. Each module includes conceptual understanding, examples, and exercises.

🎯 Bridge to LLMops / GenAI labs

After this course you will run LLMops labs (Ollama chat, Gradio UIs, OpenAI-compatible clients). Where it helps, modules include GenAI / LLMops pattern examples — same Python concepts, AI-shaped data — so those labs feel familiar, not overwhelming.

Lab idea Learn it here
import ollama / import time Module 9 — imports & time
import gradio as gr / from openai import OpenAI / from anthropic import Anthropic Module 9 — import as & from … import
API vs SDK vs client Module 9 — fundamentals
Secrets in .env vs MODEL = "..." in code Module 9 — config vs secrets
Find .env with Path / .is_file() Module 8 — pathlib
print(..., end="", flush=True) Module 1 — print options
Long SYSTEM_PROMPT / SYSTEM_CONTRACT = (...) / full += Module 3 — multi-line strings
splitlines / startswith contract checklist Module 3 — string methods
f"temperature={temp}" Module 3 — f-strings
for temp in [...] / streaming / if content: / any(...) Module 5 — loops & checks
messages roles (system/user/assistant) = memory Module 6 — list of dicts
Filter lines with list comprehension Module 6 — list comprehension
ollama.chat(...) / system= / messages.create(...) Module 7 — keyword arguments
yield full (Gradio streaming) Module 7 — generators
ChatInterface(fn=respond) Module 7 — functions as arguments
r.content[0].text / chunk.choices[0].delta.content Module 7 — objects & attributes

📚 Course Modules

🟢 Module 1: Introduction to Python


🔹 1. What is Python?

Python is a high-level, interpreted programming language developed by Guido van Rossum in 1991. It is widely used in web development, data analysis, AI/ML, automation, and more.

Key Characteristics:

  • ✔️ Simple and readable syntax
  • ✔️ Interpreted language (no need to compile)
  • ✔️ Dynamically typed
  • ✔️ Cross-platform support
  • ✔️ Rich standard libraries

🔹 2. Why Python? (Features and Applications)

Advantages:

  • ✅ Beginner-friendly
  • ✅ Works on any operating system
  • ✅ Platform-independent
  • ✅ Interactive and interpreted
  • ✅ Extensive community support
  • ✅ Huge collection of libraries and frameworks

Popular Use Cases:

  • 🌐 Web Development – Django, Flask
  • 📊 Data Science & ML – Pandas, NumPy, TensorFlow
  • 🤖 Automation & Scripting
  • 🎮 Game Development – Pygame
  • 🔐 Cybersecurity & Ethical Hacking

🔹 3. Installing Python and Setting Up Environment

🔧 Windows:

  • Download Python from https://www.python.org
  • Run the installer and check the box: ✅ Add Python to PATH
  • Open Command Prompt and verify installation:
python --version

🐧 Linux (Ubuntu) or 🖥️ macOS:

Check version:

python3 --version

If not installed:

For Ubuntu/Debian

sudo apt install python3

For macOS (using Homebrew)

brew install python

🔹 4. Introduction to print() and input() Functions

🖨️ print() – Display Output:

print("Welcome to Python!")
print("My name is John.")

🧠 Tip: print() can display multiple items separated by commas, and it will automatically insert a space between them:

print("The sum of 5 and 3 is:", 5 + 3)

🤖 GenAI / LLMops: end="" and flush=True
By default print() adds a newline. When an LLM streams tokens, print each piece on the same line and flush immediately:

print("Token 1 ", end="", flush=True)
print("Token 2 ", end="", flush=True)
print("Token 3")  # final newline

⌨️ input() – Take User Input:

name = input("Enter your name: ")
print(name)

🔹 5. Writing and Running Your First Python Script

print("Hello, World!")

Save this code in a file called hello.py and run it using:

python hello.py

📌note: Use python or python3 depending on your system.

🔹 6. Basic Arithmetic Operations in Python

a = 10
b = 5

print("Addition:", a + b)
print("Subtraction:", a - b)
print("Multiplication:", a * b)
print("Division:", a / b)
print("Modulus:", a % b)
print("Floor Division:", a // b)
print("Exponent:", a ** b)

7. Simple Interactive Program

first_name = input("please enter your first name: ")
last_name = input("please enter your last name: ")
full_name=first_name+last_name
print("hello,",full_name)

🟢 Module 2: Variables, Data Types & Type Casting


🔹 1. Variables and Constants

A variable is a name that refers to a value stored in memory. In Python, variables are dynamically created when a value is assigned.

A constant, by convention, is a variable written in all uppercase to indicate that it should not be changed (though Python does not enforce it like other languages).

PI = 3.14159      # Constant by naming convention
MAX_USERS = 100

🔧 Syntax:

variable_name = value

🧪 Example:

name = "Alice"         # String variable
age = 25               # Integer variable
height = 5.6           # Float variable
is_student = True      # Boolean variable

print(name, age, height, is_student)

🧠 Tip: You can print multiple values together using commas. Python will separate them with spaces:

🔹 Variable Naming Rules

  • ✅ Must start with a letter (a-z, A-Z) or underscore _

  • ✅ Can include letters, numbers (0-9), and underscores

  • ✅ Case-sensitive (Name and name are different)

  • ✅ Cannot use Python reserved keywords (if, while, import, etc.)

  • ✅ Valid Examples:

my_variable = 10
_myVar = "Python"
age_2024 = 30

❌ Invalid Examples:

2name = "John"      # Cannot start with a number
my-variable = 50    # Hyphens are not allowed
if = 25             # 'if' is a reserved keyword

🔹 2. Data Types in Python

Python provides built-in types to store different kinds of values.

Data Type Description Example
int Whole numbers 10, -5
float Decimal numbers 3.14, 2.0
str Sequence of characters (strings) "Hello"
bool Boolean values True, False
NoneType Represents the absence of a value None

🧪 Examples:

age = 25                 # int
price = 19.99            # float
message = "Hello"        # str
is_python_easy = True    # bool
nothing = None           # NoneType

print(type(age))
print(type(price))
print(type(message))
print(type(is_python_easy))
print(type(nothing))

🔹 3. Type Checking

Python provides type() to check the variable's type and isinstance() to verify it against a specific type or tuple of types.

🧪 Example:

x = 42
y = "Python"
z = 3.14
print(type(x))  # <class 'int'>
print(type(y))  # <class 'str'>
print(type(z))  # <class 'float'>
print(isinstance(42, int))             # True
print(isinstance("Python", float))     # False
print(isinstance(3.14, (int, float)))  # True

🔄 4. Type Casting (Type Conversion)

Python allows converting between data types using casting functions.

Function Description Example
int(x) Converts to Integer int(3.9)3
float(x) Converts to Float float("10")10.0
str(x) Converts to String str(123)"123"
bool(x) Converts to Boolean bool(0)False

🧪 Example:

num = 10
print(type(num))     # <class 'int'>

num_str = str(num)
print(type(num_str)) # <class 'str'>

pi = "3.14"
pi_float = float(pi)
print(type(pi_float)) # <class 'float'>

ℹ️ Notes:

int(3.9) → 3 (decimal removed)

float("10") → 10.0

bool(0) → False, bool(1) → True

🔹 Why Type Casting is Important with input() when doing operation with numbers The input() function always returns a string, even for numeric inputs. You need type casting to perform arithmetic.

🚫 Incorrect way (no casting):

num1 = input("Enter first number: ")  # User enters 5
num2 = input("Enter second number: ") # User enters 3
print("Sum:", num1 + num2)  # Output: 53 (string concatenation)

✅ Correct way using int():

num1 = int(input("Enter first number: "))
num2 = int(input("Enter second number: "))
print("Sum:", num1 + num2)  # Output: 8

✅ For decimal inputs using float():

num1 = float(input("Enter first decimal number: "))
num2 = float(input("Enter second decimal number: "))
print("Sum:", num1 + num2)

🟣 Module 3: Strings in Python


1️⃣ Introduction to Strings

A string in Python is a sequence of characters enclosed within single ('), double ("), or triple (''' or """) quotes.

Key Properties of Strings
✅ Immutable: Strings cannot be modified once created
✅ Indexed: Characters can be accessed using positive and negative indices
✅ Iterable: Strings can be looped through character by character


2️⃣ Creating Strings in Python

Python allows multiple ways to create a string:

# Using single, double, and triple quotes
str1 = 'Hello'
str2 = "World"
str3 = '''Multiline 
string using triple quotes.'''

print(str1, str2, str3)

🤖 GenAI / LLMops: long system prompts are just multi-line strings:

SYSTEM_PROMPT = '''You are a senior AI consultant.
Give exactly 5 ideas. No intro. No explanation.'''

🤖 GenAI / LLMops: parentheses join string literals (Week 2 contracts):

SYSTEM_CONTRACT = (
    "You are a senior SRE assistant.\n"
    "LINE1: <one short diagnostic step>\n"
    "LINE2: <one short follow-up check>\n"
)

🤖 GenAI / LLMops: build the answer as tokens arrive (full +=):

full = ""
for token in ["Hello", " Serge", "!"]:
    full += token
    print("So far:", full)

3️⃣ String Indexing and Slicing

String Indexing Table:

Characters P Y T H O N
Forward Indexing 0 1 2 3 4 5
Reverse Indexing -6 -5 -4 -3 -2 -1

String Indexing:

word = "Python"
print(word[0])    # P (First character)
print(word[-1])   # n (Last character)

String Slicing:

word = "Programming"
print(word[0:5])    # Output: Progr (0 to 4)
print(word[:6])     # Output: Progra (0 to 5)
print(word[3:])     # Output: gramming (from index 3 to end)
print(word[::2])    # Output: Pormig (every 2nd character)/(Characters at index 0, 2, 4, 6, ...)
print(word[::-1])   # Output: gnimmargorP (Reversed string)

4️⃣ Built-in String Methods (Raw Markdown Table)

Method Description
capitalize() Capitalizes first letter
casefold() Converts to lowercase (more aggressive)
center(width) Centers string in a given width
count(substring) Counts occurrences of a substring
encode() Converts string to bytes
endswith(suffix) Checks if string ends with the given suffix
expandtabs(size) Replaces tabs with spaces
find(substring) Returns the index of first occurrence
index(substring) Same as find but raises error if not found
isalnum() Checks if all characters are alphanumeric
isalpha() Checks if all characters are letters
isdigit() Checks if all characters are digits
islower() Checks if all characters are lowercase
isspace() Checks if all characters are whitespace
istitle() Checks if string is title-cased
isupper() Checks if all characters are uppercase
join(iterable) Joins elements of an iterable with the string
ljust(width) Left-aligns string within given width
lower() Converts to lowercase
lstrip() Removes leading whitespace
replace(old, new) Replaces old substring with new
rfind(substring) Finds last occurrence of substring
rindex(substring) Like rfind, but raises error if not found
rjust(width) Right-aligns string
rstrip() Removes trailing whitespace
split(sep) Splits string into list
splitlines() Splits string at line breaks
startswith(prefix) Checks if string starts with given prefix
strip() Removes leading/trailing whitespace
swapcase() Swaps case of all characters
title() Converts to title case
upper() Converts to uppercase
zfill(width) Pads string with zeros

5️⃣ String Methods and Functions

# Finding String Length
text = "Python"
print(len(text))  # Output: 6

# Changing Case
text = "hello world"
print(text.upper())       # HELLO WORLD
print(text.lower())       # hello world
print(text.title())       # Hello World
print(text.capitalize())  # Hello world

# Checking String Content
print("Python".isalpha())    # True
print("1234".isdigit())      # True
print("Hello123".isalnum())  # True
print("   ".isspace())       # True

# Searching in Strings
text = "Python programming"
print(text.find("prog"))  # Output: 7
print(text.count("o"))    # Output: 2

# Replacing and Splitting
text = "I love Python"
print(text.replace("love", "like"))  # I like Python

words = text.split()
print(words)  # ['I', 'love', 'Python']

joined = "-".join(words)
print(joined)  # I-love-Python

# Checking Prefix and Suffix
text = "hello.py"
print(text.startswith("hello"))  # True
print(text.endswith(".py"))      # True

# Stripping Whitespace
text = "  hello  "
print(text.strip())   # 'hello'
print(text.lstrip())  # 'hello  '
print(text.rstrip())  # '  hello'

🤖 GenAI / LLMops: contract checklist (splitlines + startswith):

text = "LINE1: Check load balancer health\nLINE2: Inspect upstream pods\n"
print(text.strip().startswith("LINE1:"))
lines = text.strip().splitlines()
print(lines[0].startswith("LINE1:"))
print(len(lines) == 2)

6️⃣ String Formatting

# Using format()
name = "Alice"
age = 25
print("My name is {} and I am {} years old.".format(name, age))
# Using f-strings (Python 3.6+)
print(f"My name is {name} and I am {age} years old.")

🤖 GenAI / LLMops: label parameters and timing (same style as Lab 1):

temp = 0.7
waited = 2.3
print(f"--- temperature={temp} ---")
print(f"Waited {waited:.1f}s in silence.")  # :.1f → one decimal place

7️⃣ Escape Sequences

Escape Sequence Meaning
\n Newline
\t Tab
\\ Backslash
print("Hello\nWorld")  # Newline
print("Name:\tAlice")  # Tab

8️⃣ Raw Strings

# Raw strings ignore escape sequences
print(r"C:\newfolder\test")  # Output: C:\newfolder\test

🟣 Module 4: Operators and Expressions

Operators are symbols that perform operations on variables and values.
Expressions are combinations of values, variables, and operators that produce a result.

In this module, we will explore different types of operators in Python and how they work.


➕ 1. Arithmetic Operators

These operators perform mathematical operations like addition, subtraction, multiplication, and division.

a = 10
b = 3

print("Addition:", a + b)        # 13
print("Subtraction:", a - b)     # 7
print("Multiplication:", a * b)  # 30
print("Division:", a / b)        # 3.3333
print("Floor Division:", a // b) # 3
print("Modulus:", a % b)         # 1
print("Exponentiation:", a ** b) # 1000
Operator Symbol Example Result
Addition + 10 + 5 15
Subtraction - 10 - 5 5
Multiplication * 10 * 5 50
Division / 10 / 3 3.3333
Floor Division // 10 // 3 3 (Removes decimal part)
Modulus % 10 % 3 1 (Remainder)
Exponentiation ** 2 ** 3 8 (2³)

🧮 2. Comparison (Relational) Operators

These operators return True or False based on a condition.

x = 10
y = 5

print(x > y)    # True
print(x < y)    # False
print(x == 10)  # True
print(y != 5)   # False
Operator Meaning Example Result
== Equal to 5 == 5 True
!= Not equal to 5 != 3 True
> Greater than 10 > 5 True
< Less than 2 < 5 True
>= Greater than or equal to 3 >= 3 True
<= Less than or equal to 4 <= 2 False

⚙️ 3. Logical Operators

Used to combine multiple conditions.

a = True
b = False

print(a and b)  # False
print(a or b)   # True
print(not a)    # False
Operator Meaning Example Result
and Returns True if both conditions are True (5 > 2) and (10 > 3) True
or Returns True if at least one is True (5 > 2) or (10 < 3) True
not Reverses the Boolean result not (5 > 2) False

📝 4. Assignment Operators

Used to assign or modify values of variables.

x = 10
x += 5  # x = x + 5
print(x)  # 15

x *= 2  # x = x * 2
print(x)  # 30
Operator Meaning Example Equivalent To
= Assign value x = 10 x = 10
+= Add & assign x += 5 x = x + 5
-= Subtract & assign x -= 3 x = x - 3
*= Multiply & assign x *= 2 x = x * 2
/= Divide & assign x /= 2 x = x / 2
//= Floor divide & assign x //= 2 x = x // 2
%= Modulus & assign x %= 3 x = x % 3
**= Exponentiate & assign x **= 2 x = x ** 2

🧭 5. Identity Operators

🧠 Identity Operators Check if two variables reference the same object in memory.

a = [1, 2, 3]
b = a
c = [1, 2, 3]

print(a is b)   # True
print(a is c)   # False
print(a == c)   # True
Operator Meaning Example
is True if objects are identical x is y
is not True if objects are not same x is not y

📦 Membership Operators

Used to check if a value exists in a collection.

word = "apple"

print("a" in word)      # True — 'a' is in "apple"
print("z" in word)      # False — 'z' is not in "apple"
print("pp" in word)     # True — "pp" is a substring of "apple"
print("app" not in word) # False — "app" *is* in "apple"
Operator Meaning Example
in True if value exists in the sequence 'a' in 'apple'
not in True if value does not exist 5 not in [1, 2, 3]

🧭 Module 5: Control Flow Statements

Control flow statements allow programs to make decisions and repeat code blocks based on conditions.


✅ 1. Conditional Statements

🔹 1.1 The if Statement

Executes a block of code only if the condition is True.

🔧 Syntax:

if condition:
    # Code to execute if condition is True

📌 Example: Check if a number is positive

num = int(input("Enter a number: "))

if num > 0:
    print("The number is positive.")

🔹 1.2 The if-else Statement Executes one of two blocks depending on the condition.

🔸 if-else Flow

    ┌───────────────┐
    │  Condition ?  │
    └─────┬─────────┘
          │
    ┌─────▼───────┐
 Yes│  Execute     │
    │  if-block    │
    └─────┬────────┘
          │
       ┌──▼──┐
       │ End │
       └─────┘
          │
         No
          │
    ┌─────▼───────┐
    │ Execute     │
    │ else-block  │
    └─────┬────────┘
          │
       ┌──▼──┐
       │ End │
       └─────┘

🔧 Syntax:

if condition:
    # Executes if condition is True
else:
    # Executes if condition is False

📌 Example: Even or Odd

num = int(input("Enter a number: "))

if num % 2 == 0:
    print("Even number")
else:
    print("Odd number")

🔹 1.3 The if-elif-else Ladder Used to test multiple conditions.

🔸 if-elif-else Flow

     ┌──────────────┐
     │ Condition 1? │
     └─────┬────────┘
           │Yes
     ┌─────▼───────┐
     │ Execute     │
     │ if-block    │
     └─────┬────────┘
           │
        ┌──▼──┐
        │ End │
        └─────┘
           │
          No
           │
     ┌─────▼───────┐
     │ Condition 2?│
     └─────┬────────┘
           │Yes
     ┌─────▼───────┐
     │ Execute     │
     │ elif-block  │
     └─────┬────────┘
           │
        ┌──▼──┐
        │ End │
        └─────┘
           │
          No
           │
     ┌─────▼───────┐
     │ Execute     │
     │ else-block  │
     └─────┬────────┘
           │
        ┌──▼──┐
        │ End │
        └─────┘

🔧 Syntax:

if condition1:
    # Executes if condition1 is True
elif condition2:
    # Executes if condition2 is True
else:
    # Executes if none are True

📌 Example: Positive, Negative, or Zero

num = int(input("Enter a number: "))

if num > 0:
    print("Positive Number")
elif num < 0:
    print("Negative Number")
else:
    print("Zero")

🔁 2. Looping Constructs

Loops are used to repeat a block of code.

🔸 for Loop Flow

    ┌───────────────┐
    │  Initialize   │
    │  Loop Var     │
    └─────┬─────────┘
          │
    ┌─────▼───────┐
    │ Condition ? │
    └─────┬───────┘
          │Yes
    ┌─────▼────────┐
    │ Execute Loop │
    │   Body       │
    └─────┬────────┘
          │
    ┌─────▼───────┐
    │ Increment   │
    │  Loop Var   │
    └─────┬───────┘
          │
         (Repeat)
          │
         No
          │
    ┌─────▼────┐
    │   End    │
    └──────────┘

🔹 Understanding range() Function Syntax:

range(start, stop, step)

start: Optional, default is 0

stop: Required (excluded)

step: Optional, default is 1

Example:

for i in range(1, 6):
    print(i)

Output:

1
2
3
4
5

🔹 2.1 for Loop Used for iterating over sequences like list, tuple, string.

📌 Example: Iterate 1 to 5

for i in range(1, 6):
    print(i)

📌 Example: Iterate Over List

fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(fruit)

📌 Example: Iterate Over Tuple

numbers = (10, 20, 30, 40)
for num in numbers:
    print(num)

📌 Example: Iterate Over String

word = "Python"
for char in word:
    print(char)

🤖 GenAI / LLMops: loop over parameter values (e.g. try several temperatures):

temperatures = [0.0, 0.7, 1.5]
question = "Explain RAG in one sentence."

for temp in temperatures:
    # Lab 1: ollama.chat(..., options={"temperature": temp})
    print(f"\n--- temperature={temp} ---")

🤖 GenAI / LLMops: stream chunks as they arrive:

chunks = ["RAG ", "retrieves ", "documents ", "then ", "generates ", "an answer."]

for chunk in chunks:
    print(chunk, end="", flush=True)
# Same idea as: for chunk in ollama.chat(..., stream=True):

🤖 GenAI / LLMops: skip empty stream pieces (truthiness):

stream_pieces = ["Hello", None, " ", "", "world"]
full = ""
for piece in stream_pieces:
    if piece:          # skip None and ""
        full += piece
# Same idea as: if chunk.choices[0].delta.content:

🤖 GenAI / LLMops: any(...) for checklist (Week 2 Lab 1):

lines = ["LINE1: Check LB health", "LINE2: Inspect pods"]
print(any(ln.startswith("LINE2:") for ln in lines))  # True

🔹 2.2 while Loop Runs while the condition is True.

🔸 while Loop Flow

    ┌───────────────┐
    │ Initialization│
    └─────┬─────────┘
          │
    ┌─────▼───────┐
    │ Condition ? │
    └─────┬───────┘
          │Yes
    ┌─────▼────────┐
    │ Execute Loop │
    │   Body       │
    └─────┬────────┘
          │
    ┌─────▼───────┐
    │ Update      │
    │ Condition   │
    └─────┬───────┘
          │
         (Repeat)
          │
         No
          │
    ┌─────▼────┐
    │   End    │
    └──────────┘

📌 Example: 1 to 5

i = 1
while i <= 5:
    print(i)
    i += 1

🔀 3. Control Statements (break, continue, pass)

⛔ 3.1 break Statement Stops the loop immediately.

📌 Example: Stop at 5

for i in range(1, 11):
    if i == 5:
        break
    print(i)

Output:

1
2
3
4

📌 Example: break — Stop when input is correct:

while True:
    pwd = input("Enter password: ")
    if pwd == "admin123":
        print("Access granted.")
        break

➿ 3.2 continue Statement Skips current iteration and continues.

📌 Example: Skip 5

for i in range(1, 11):
    if i == 5:
        continue
    print(i)
1
2
3
4
6
7
8
9
10

📌Example: continue — Skip vowels:

for char in "education":
    if char in "aeiou":
        continue
    print(char)

📭 3.3 pass Statement Does nothing — used as a placeholder.

📌 Example:

for i in range(5):
    pass  # Placeholder for future code

🧩 Module 6: Lists, Tuples, Dictionaries, and Sets in Python


1.📌 Lists in Python (Ordered & Mutable)

📖 Introduction to Lists A list in Python is an ordered, mutable collection that can hold multiple data types. You can add, update, delete, and rearrange elements easily.

🛠️ Creating a List

# Empty list
empty_list = []

# List with mixed data types
mixed_list = [10, "Python", 3.14, True]

# Nested list
nested_list = [[1, 2, 3], ["a", "b", "c"]]

print(mixed_list)
print(nested_list)

🤖 GenAI / LLMops: list of dictionaries = chat history
LLM chat APIs take a list of message dicts (role + content):

messages = [
    {"role": "user",      "content": "Hi, I am Serge."},
    {"role": "assistant", "content": "Hello Serge! Nice to meet you."},
    {"role": "user",      "content": "What is my name?"},
]

print(messages[0]["role"])      # "user"
print(messages[0]["content"])   # "Hi, I am Serge."
print(messages[-1]["content"])  # last question

🤖 Week 2 Lab 1: three roles — system (contract), user (human), assistant (past model reply).
Your messages list is the memory. No history → amnesia.

reply1 = "Check the load balancer, then the payments-api pods."
messages_with_memory = [
    {"role": "user", "content": "My service name is payments-api. Help with 503."},
    {"role": "assistant", "content": reply1},  # exact past reply resent
    {"role": "user", "content": "What was my service name?"},
]

🔍 Accessing Elements (Indexing & Slicing)

numbers = [10, 20, 30, 40, 50]

print(numbers[0])     # First element → 10
print(numbers[-1])    # Last element → 50
print(numbers[1:4])   # Sublist → [20, 30, 40]
print(numbers[:3])    # → [10, 20, 30]
print(numbers[::2])   # Every second element → [10, 30, 50]

📝 Modifying and Updating Lists

fruits = ["apple", "banana", "cherry"]
fruits[1] = "blueberry"  # Replace banana with blueberry
print(fruits)

🔧 Common List Methods

append(), extend(), insert(), remove(), pop(), clear(), 
index(), count(), sort(), reverse(), copy()

📋 Method Reference Table

Method Description
append() Adds a single element at the end
extend() Adds multiple elements from another list
insert() Inserts an element at a specific index
remove() Removes the first occurrence of a value
pop() Removes and returns element by index
clear() Removes all elements from the list
index() Returns the first index of a value
count() Counts how many times a value appears
sort() Sorts the list in ascending order
reverse() Reverses the list order
copy() Returns a shallow copy of the list

Examples:

fruits = ["apple", "banana"] fruits.append("cherry") print(fruits)

numbers = [1, 2, 3] numbers.extend([4, 5]) print(numbers)

colors = ["red", "blue", "green"] colors.insert(1, "yellow") print(colors)

🎯 List Comprehension

# Squares of numbers
squares = [x**2 for x in range(1, 6)]
print(squares)

# Filter even numbers
numbers = [1, 2, 3, 4, 5, 6]
evens = [num for num in numbers if num % 2 == 0]
print(evens)

🤖 GenAI / LLMops: keep only non-empty lines (Week 2 checklist):

text = "LINE1: Check LB\n\nLINE2: Inspect pods\n"
lines = [ln for ln in text.strip().splitlines() if ln.strip()]
print(len(lines) == 2)

2.📦 Tuples in Python (Ordered & Immutable)

📖 Introduction to Tuples A tuple is similar to a list but immutable (cannot be changed once created).

# Creating Tuples
empty_tuple = ()
mixed_tuple = (10, "Python", 3.14, True)
single_element = (5,)  # Important: Comma needed
nested_tuple = ((1, 2), ("a", "b"))

print(mixed_tuple)

🧭 Indexing & Slicing Tuples

numbers = (10, 20, 30, 40, 50)
print(numbers[0])      # First element
print(numbers[-1])     # Last element
print(numbers[1:4])    # Slice → (20, 30, 40)

⚠️ Tuple Immutability

fruits = ("apple", "banana", "cherry")
# fruits[1] = "blueberry"  ❌ Error!

🔧 Common Tuple Methods

numbers = (1, 2, 1, 4, 1)
print(numbers.count(1))     # → 3
print(numbers.index(4))     # → 3

📦 Tuple Packing & Unpacking

person = ("John", 25, "Engineer")
name, age, job = person
print(name, age, job)

🔁 Conversion Between List and Tuple

# List → Tuple
lst = [1, 2, 3]
tpl = tuple(lst)

# Tuple → List
tpl2 = ("red", "green")
lst2 = list(tpl2)

3.🗂️ Dictionaries in Python (Key-Value Pairs)

📖 Introduction A dictionary stores data in key-value format. Keys must be unique.

student = {
    "name": "Alice",
    "age": 22,
    "grade": "A",
    "subjects": ["Math", "Physics"]
}

🔍 Accessing & Modifying Dictionary

print(student["name"])          # Alice
print(student.get("email", "N/A"))  # Safe access


# Modify
student["city"] = "New York"
student["grade"] = "A+"
del student["age"]

🔧 Common Dictionary Methods

Method Description
get() Gets value of a key safely
keys() Returns all keys
values() Returns all values
items() Returns all key-value pairs
update() Merges another dictionary
pop() Removes item by key
popitem() Removes the last inserted item
setdefault() Sets a default value if key doesn't exist
clear() Clears all entries
student.update({"hobby": "Reading"})
student.pop("city")
student.popitem()

🔁 Looping Through Dictionary

for key in student:
    print(key, ":", student[key])

for key, value in student.items():
    print(f"{key} -> {value}")

🧩 Nested Dictionary

company = {
    "emp1": {"name": "John", "role": "Manager"},
    "emp2": {"name": "Alice", "role": "Dev"}
}
print(company["emp1"]["role"])  # Manager

🤖 GenAI / LLMops: nested extraction from an API response
Same pattern as Lab 1: r["message"]["content"]

r = {
    "model": "llama3.2:1b",
    "message": {
        "role": "assistant",
        "content": "Hello Serge! Nice to meet you."
    },
    "done": True
}

print(r["message"]["content"])  # the assistant text you display
options = {"temperature": 0.7}
print(options["temperature"])

🤖 GenAI / LLMops: nested list + dict (OpenAI chunk shape with dicts):

chunk = {
    "choices": [
        {"delta": {"content": "Hello Serge!"}}
    ]
}
print(chunk["choices"][0]["delta"]["content"])
# Module 7 shows the same path with object attributes: chunk.choices[0].delta.content

🧠 Dictionary Comprehension

squares = {x: x**2 for x in range(1, 6)}
print(squares)

4.🔗 Sets in Python (Unordered & Unique)

📖 Introduction A set is:

Unordered

Mutable

Contains unique elements

fruits = {"apple", "banana", "apple", "cherry"}
print(fruits)  # Duplicates removed

🧪 Set Operations

Operation Syntax Description
Union A.union(B) Combines all unique elements
Intersection A.intersection(B) Common elements only
Difference A.difference(B) Elements in A not in B
Symmetric Difference A.symmetric_difference(B) Unique in A or B, not both
A = {1, 2, 3}
B = {3, 4, 5}
print(A.union(B))             # → {1, 2, 3, 4, 5}
print(A.intersection(B))      # → {3}
print(A.difference(B))        # → {1, 2}
print(A.symmetric_difference(B))  # → {1, 2, 4, 5}

⚙️ Modifying Sets

fruits.add("orange")
fruits.update(["grape", "mango"])

fruits.remove("banana")   # ❌ Error if not found
fruits.discard("banana")  # ✅ No error
random_element = fruits.pop()
fruits.clear()

🔁 Iterating Sets

for item in fruits:
    print(item)

🧠 Set Comprehension

squared = {x**2 for x in range(1, 6)}
print(squared)  # → {1, 4, 9, 16, 25}

🧠 Module 7: Python Functions


Functions help in organizing code into reusable blocks. In this module, we’ll learn how to define and use functions effectively.

🔹 1. Defining and Calling Functions

A function is defined using the def keyword, followed by a name, parentheses () (with optional parameters), and a colon :

# Function Definition
def greet():
    print("Hello! Welcome to Python.")

# Function Call
greet()

✅ A function must be defined before it's called. 📝 Indentation is critical inside function blocks.

🔹 2. Function Parameters and Return Values

📌 2.1 Parameters vs. Arguments

Parameters → Variables in the function definition.

Arguments → Actual values passed when calling the function.

def greet(name):
    print(f"Hello, {name}!")

# Calling the function with an argument
greet("Alice")

📌 2.2 Returning a Value

Use return to send a value back to the caller.

def square(num):
    return num * num

result = square(4)
print("Square:", result)

🚫 A function stops execution once return is encountered.

🔹 3. Types of Function Arguments

Python supports four types of function arguments:

Argument Type Description Example
Positional Arguments Passed in the correct order func(1, 2)
Default Arguments Parameters with default values func(a=5, b=10)
Keyword Arguments Specify argument names during function call func(b=10, a=5)
Variable-Length Arguments Accepts multiple values using *args/**kwargs func(1, 2, 3, key="value")

📌 3.1 Positional Arguments Arguments passed in the correct order.

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

print(add(3, 5))  # ✅
# print(add(3))   # ❌ Error: missing argument

⚙️ 3.2 Default Arguments Assign default values if no argument is passed.

def greet(name="Guest"):
    print(f"Hello, {name}!")

greet()         # Uses default → "Guest"
greet("Alice")  # Overrides default

📝 Default parameters must be placed after non-defaults.

🧾 3.3 Keyword Arguments Specify arguments using parameter names (order doesn't matter).

def describe_pet(animal, name):
    print(f"{name} is a {animal}.")

describe_pet(animal="dog", name="Buddy")
describe_pet(name="Kitty", animal="cat")

🤖 GenAI / LLMops: calling AI functions with named parameters
Labs call APIs like ollama.chat(model=..., messages=..., options=...). Practice the same style:

def chat(model, messages, stream=False, options=None):
    if options is None:
        options = {}
    return {
        "model": model,
        "message": {
            "role": "assistant",
            "content": f"Reply from {model}"
        },
    }

r = chat(
    model="llama3.2:1b",
    messages=[{"role": "user", "content": "Hi, I am Serge."}],
)
print("First call:", r["message"]["content"])

r = chat(model="llama3.2:1b", messages=messages, options={"temperature": 0.7})

🤖 Week 2: system= separate from messages, then read r.content[0].text:

r = messages_create(
    model="claude-haiku",
    system=SYSTEM_CONTRACT,
    messages=[{"role": "user", "content": "What should I check for a 503?"}],
)
# Anthropic path: r.content[0].text

🌟 3.4 Variable-Length Arguments ➕ *args → Non-keyword variable arguments

def add_numbers(*args):
    return sum(args)

print(add_numbers(1, 2, 3, 4))  # Output: 10

📦 *args is treated as a tuple of values.

🧩 **kwargs → Keyworded variable arguments

def describe_person(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

describe_person(name="Alice", age=25, city="New York")

🔑 **kwargs is treated as a dictionary of named arguments.

⚡ 4️⃣ Lambda Functions (Anonymous Functions) A lambda is a small, single-line function.

📐 Syntax

lambda arguments: expression

Example:

cube = lambda x: x ** 3
print(cube(3))  # Output: 27

5️⃣ yield — Generators (Gradio streaming)

return sends one value and stops. yield sends a value and pauses so the function can continue. Gradio UIs update the chat as the answer grows:

def stream_reply(tokens):
    full = ""
    for token in tokens:
        full += token
        yield full

for partial in stream_reply(["Hi, ", "I ", "am ", "an ", "AI."]):
    print(partial)

🤖 Lab 5 pattern:

def respond(message, history):
    full = ""
    for token in ["Idea 1...", " Idea 2..."]:
        if token:
            full += token
            yield full

6️⃣ Functions as Arguments (fn=respond)

A function name without () is a value you can pass. Gradio does ChatInterface(fn=respond) and calls your function later:

def run_chat(fn, user_text):
    return fn(user_text, history=[])

def my_bot(message, history):
    return f"You said: {message}"

print(run_chat(fn=my_bot, user_text="Hello"))  # pass my_bot, not my_bot()

7️⃣ Objects & Attributes — Reading SDK Code

You do not need a full OOP course yet. You need to read dots:

client.chat.completions.create(...) and chunk.choices[0].delta.content

class FakeDelta:
    def __init__(self, content):
        self.content = content

class FakeChoice:
    def __init__(self, content):
        self.delta = FakeDelta(content)

class FakeChunk:
    def __init__(self, content):
        self.choices = [FakeChoice(content)]

chunk = FakeChunk("Hello Serge!")
print(chunk.choices[0].delta.content)  # Hello Serge!

🤖 Week 2 Anthropic path (same idea, different names):

print(r.content[0].text)  # object → list[0] → .text

Full FakeOpenAI / FakeMessage examples: see 07-Functions in Python/module7.py.

📁 Module 08: File Handling in Python

File handling allows us to read and write data to files. Python provides built-in functions to handle files easily and efficiently.

🗂️ File Modes in Python

Mode Description
"r" Read (default mode)
"w" Write (overwrites file if it exists)
"a" Append (adds content to the file)
"x" Exclusive creation (fails if file exists)
"rb" Read binary
"wb" Write binary
"ab" Append binary

📖 Opening and Closing Files

file = open("example.txt", "r")  # Open in read mode
file.close()                     # Close the file

✅ Always close the file after use!

✍️ Writing to a File

file = open("sample.txt", "w")
file.write("Hello, this is a test file.")
file.close()

📚 Reading from Files 🔹 Reading the entire content

file = open("sample.txt", "r")
content = file.read()
print(content)
file.close()

🔹 Reading line by line

file = open("sample.txt", "r")
line = file.readline()
print(line)
file.close()

🔹 Reading all lines into a list

file = open("sample.txt", "r")
lines = file.readlines()
print(lines)
file.close()

📝 Writing Multiple Lines

lines = ["Line 1\n", "Line 2\n", "Line 3\n"]
file = open("output.txt", "w")
file.writelines(lines)
file.close()

➕ Appending to a File

file = open("output.txt", "a")
file.write("This line will be appended.\n")
file.close()

🤝 Using with Statement (Auto-closes File)

with open("output.txt", "r") as file:
    content = file.read()
    print(content)
# No need to explicitly close

🖼️ Working with Binary Files 🔹 Reading a binary file

with open("image.jpg", "rb") as file:
    data = file.read()
    print("Binary content:", data[:20])  # First 20 bytes
with open("copy.jpg", "wb") as new_file:
    new_file.write(data)

🔍 Check if File Exists

import os

if os.path.exists("sample.txt"):
    print("File exists")
else:
    print("File not found")

🤖 GenAI / LLMops: find .env with pathlib (Week 2 Lab 1):

from pathlib import Path

here = Path.cwd().resolve()
loaded_from = None
for candidate in [here / ".env", here.parent / ".env", here.parent.parent / ".env"]:
    if candidate.is_file():
        loaded_from = candidate
        break
print("Would load .env from:", loaded_from)

❌ Deleting a File

import os

os.remove("sample.txt")

✅ Tips:

Always close the file or use with to handle it automatically.

Use binary mode for images or non-text files.

File handling is crucial for logging, storing data, and working with external files.


🟢 Module 9: Important Modules

Python’s power comes from modules. You import a module to use its functions. Lab 1 uses import ollama / import time. Lab 5 uses import gradio as gr, from openai import OpenAI, and from dotenv import load_dotenv.


🔹 0. What does import do?

import loads another module into your program. Without it, Python does not know that name.

import time       # standard library — comes with Python
# import ollama   # third-party — install first: pip install ollama
Pattern Meaning Lab example
import ollama Use ollama.chat(...) Lab 1
import time Use time.time() Lab 1
import gradio as gr Alias — shorter name Lab 5
from openai import OpenAI Import one class/function directly Lab 5
from dotenv import load_dotenv Import one function Lab 5
import datetime as dt          # same idea as: import gradio as gr
print(dt.date.today())

from math import sqrt          # same idea as: from openai import OpenAI
print(sqrt(16))

🔹 0.1 time — measure wait vs streaming feel

import time

t0 = time.time()
time.sleep(1)
print(f"Waited {time.time() - t0:.1f}s")

🔹 1. OS and System Operations (os, sys)

import os
print(os.getcwd())
print(os.listdir("."))

🔹 3. Environment variables & config vs secrets (Lab 5)

  • Config (safe in code): MODEL = "claude-sonnet-4-6"
  • Secrets (never commit): API keys in .env, loaded with load_dotenv()
from dotenv import load_dotenv
import os

load_dotenv()

MODEL = "claude-sonnet-4-6"                         # config — OK in code
api_key = os.environ.get("ANTHROPIC_API_KEY")       # secret — from .env
print("API key loaded:", bool(api_key))             # never print the raw key

.env (not in git):

ANTHROPIC_API_KEY=sk-...

🔹 4. API vs SDK vs client (Week 2 Lab 1 words)

Term Meaning
API Remote interface your program calls
SDK Official client library you import (anthropic, openai, …)
client Object the SDK gives you: client = Anthropic()
# from anthropic import Anthropic
# client = Anthropic()
# r = client.messages.create(model=..., messages=...)

The SDK talks to the API for you — you call Python methods, not raw HTTP (unless you use requests).


🔹 2–7. Other modules covered in module9.py

  • subprocess — run shell commands
  • requests — HTTP / API calls
  • Docker / Kubernetes helpers
  • Cloud / IaC (boto3, Terraform)
  • CI/CD & Git automation

See 09-Important modules/module9.py for full runnable examples.

About

Python Curriculum

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages