Python Complete Course — CodeStudio Vault
0 / 69 topics
Python Fundamentals → Advanced

Complete Python Reference Course

Every concept from the official Python cheatsheet — explained line by line with syntax highlighting, real code examples, step-by-step breakdowns, and interactive progress tracking. Zero fluff, all signal.

10Modules
69Topics
3.6+Python Version
100%Free
Overall Progress — 0 of 69 topics completed
0Completed
69Remaining
0%Progress
01
Module 1 — Getting Started
Hello World, variables, data types, arithmetic, slicing, f-strings intro
0% · 0/11 done
1.1 — Hello World
Expand →

Your First Python Program

Python is an interpreted language — you write code and it runs immediately, no compilation needed. The built-in print() function outputs text to the console. The famous "Hello World" is traditionally the very first program any programmer writes.

Python
>>> print("Hello, World!")
Hello, World!

The >>> is the Python interactive shell prompt — it means you're typing directly into the Python interpreter. In a .py file, just write print("Hello, World!") without the prompt.

1.2 — Variables
Expand →

What is a Variable?

A variable is a named container that holds a value. Python is dynamically typed — you don't declare the type; Python figures it out from the value you assign. Variables are created the moment you assign a value to them with =.

Python
age  = 18       # age is of type int
name = "John"   # name is now of type str
print(name)    # prints: John

Python cannot declare a variable without assignment. Unlike C++ or Java, you can't write int age; — you must always assign a value: age = 18.

1.3 — Data Types Overview
Expand →

Python's Built-in Types

Python has several built-in data types organized by category. Every value in Python is an object with a type. You can check any value's type with type().

CategoryTypesExample
Textstr"hello"
Numericint, float, complex42, 3.14, 1j
Sequencelist, tuple, range[1,2,3]
Mappingdict{"key": "value"}
Setset, frozenset{"a","b","c"}
BooleanboolTrue, False
Binarybytes, bytearray, memoryviewb"hello"
1.4 — Numbers & Booleans
Expand →

Numeric Types

Python has three numeric types: int (whole numbers, unlimited precision), float (decimal numbers, 64-bit), and complex (numbers with a real and imaginary part: a + bj). Booleans are actually a subclass of int: True == 1 and False == 0.

Python
x = 1      # int
y = 2.8    # float
z = 1j     # complex

>>> print(type(x))
<class 'int'>

my_bool = True
my_bool = False

bool(0)   # => False  (zero is falsy)
bool(1)   # => True   (non-zero is truthy)
1.5 — Arithmetic Operators
Expand →

Math in Python

Python supports all standard math operations. Key differences from other languages: / always returns a float (true division), while // does floor division (integer result). ** is the power/exponentiation operator. % is modulo (remainder).

Python
result = 10 + 30   # => 40   (addition)
result = 40 - 10   # => 30   (subtraction)
result = 50 * 5    # => 250  (multiplication)
result = 16 /  4   # => 4.0  (float division — always float!)
result = 16 // 4   # => 4    (floor/integer division)
result = 25 %  2   # => 1    (modulo — remainder of 25÷2)
result =  5 ** 3   # => 125  (exponent — 5 to the power 3)

Python's / always produces a float: 16 / 4 = 4.0, not 4. Use // when you need an integer result. This is different from C/C++ where 16/4 = 4.

1.6 — Plus-Equals (+=) and Compound Assignment
Expand →

Shorthand Assignment Operators

Python supports shorthand operators that combine an operation with assignment. x += 5 is exactly equivalent to x = x + 5. Works with all arithmetic operators: +=, -=, *=, /=, //=, %=, **=. Also works on strings for concatenation.

Python
counter = 0
counter += 10            # => 10  (same as counter = counter + 10)

counter = 0
counter = counter + 10  # => 10  (verbose version — same result)

message = "Part 1."
message += "Part 2."    # => "Part 1.Part 2."  (string concat)
1.7 — Type Casting
Expand →

Converting Between Types

Type casting (or type conversion) converts a value from one type to another using built-in functions: int(), float(), str(), bool(), etc. Useful when reading user input (always a string) and you need a number.

1To Integer
Python
x = int(1)     # x will be 1
y = int(2.8)   # y will be 2  (truncates, NOT rounds)
z = int("3")   # z will be 3  (string "3" → int 3)
2To Float
Python
x = float(1)      # x will be 1.0
y = float(2.8)    # y will be 2.8
z = float("3")    # z will be 3.0
w = float("4.2")  # w will be 4.2
3To String
Python
x = str("s1")  # x will be 's1'
y = str(2)     # y will be '2'  (number → string)
z = str(3.0)   # z will be '3.0'
1.8 — Lists (Quick Intro)
Expand →

Ordered, Mutable Collections

A list is an ordered, mutable (changeable) sequence of items. Items can be of different types. Append items with .append(). Full coverage in Module 3.

Python
mylist = []
mylist.append(1)
mylist.append(2)
for item in mylist:
    print(item)   # prints 1, then 2
1.9 — If / Else (Quick Intro)
Expand →

Conditional Branching

Python uses indentation (spaces/tabs) — NOT curly braces — to define code blocks. The if block runs when the condition is True, else when it's False. Full coverage in Module 4.

Python
num = 200
if num > 0:
    print("num is greater than 0")
else:
    print("num is not greater than 0")
1.10 — Loops Quick Intro
Expand →

Repeating Actions

for loops iterate over a sequence. range(n) generates numbers from 0 to n-1. break exits the loop early. The else block after a loop runs only if the loop completed without a break.

Python
for item in range(6):
    if item == 3: break
    print(item)
else:
    print("Finally finished!")
# Prints: 0, 1, 2 (stops at 3 due to break, else skipped)
1.11 — Functions Quick Intro
Expand →

Reusable Code Blocks

A function is a named block of reusable code. Define with def, call by name. Full coverage in Module 6.

Python
>>> def my_function():
...     print("Hello from a function")
...
>>> my_function()
Hello from a function
02
Module 2 — Strings & F-Strings
Indexing, slicing, methods, formatting, f-string fill/align/types
0% · 0/10 done
2.1 — String Declaration
Expand →

Creating Strings

Strings are sequences of characters. Use single ' or double " quotes — both work identically. For multi-line strings, use triple quotes """ or '''.

Python
hello = "Hello World"   # double quotes
hello = 'Hello World'   # single quotes — same result

multi_string = """Multiline Strings
Lorem ipsum dolor sit amet,
consectetur adipiscing elit"""
# Triple quotes preserve newlines and indentation
2.2 — String Indexing & Array-like Access
Expand →

Characters by Position

Strings are sequences — each character has an index. Positive indices count from the start (0-based); negative indices count from the end (-1 is last). You can loop through characters with a for loop.

Python
>>> hello = "Hello, World"
>>> print(hello[1])    # => e  (index 1)
>>> print(hello[-1])   # => d  (last character)

# Loop through each character
for char in "foo":
    print(char)   # prints: f, then o, then o
2.3 — String Slicing
Expand →

Extracting Substrings

Slicing extracts a portion of a string using s[start:end] or s[start:end:step]. The start index is inclusive, end is exclusive. Omitting start/end defaults to the beginning/end of the string.

Python — Index map
# ┌───┬───┬───┬───┬───┬───┬───┐
# | m | y | b | a | c | o | n |
# └───┴───┴───┴───┴───┴───┴───┘
#   0   1   2   3   4   5   6   7
#  -7  -6  -5  -4  -3  -2  -1

s = 'mybacon'
s[2:5]        # => 'bac'   (index 2,3,4 — end is exclusive)
s[0:2]        # => 'my'
s[:2]         # => 'my'    (omit start = from beginning)
s[2:]         # => 'bacon' (omit end = to the end)
s[:]           # => 'mybacon' (full copy)
s[-5:-1]      # => 'baco'  (negative indices)

# With stride (step)
s = '12345' * 5   # => '1234512345...' (repeated 5 times)
s[::5]           # => '11111'  (every 5th char)
s[::-1]          # => '54321...' (reversed!)
2.4 — String Methods: len, join, endswith, check, concat
Expand →

Built-in String Operations

Python strings have many built-in methods and operations. Key ones: len() for length, in/not in for membership checks, + for concatenation, * for repetition, .join() to join a list into a string, .endswith() to check endings.

Python
# Length
>>> len("Hello, World!")
13

# Repetition (multiple copies)
>>> '===+' * 3
'===+===+===+'

# Membership check
>>> 'spam' in 'I saw spamalot!'
True
>>> 'spam' not in 'Holy Grail'
True

# Concatenation
>>> 'spam' + 'egg'
'spamegg'

# join — glue list items into a string
>>> "#".join(["John", "Peter", "Vicky"])
'John#Peter#Vicky'

# endswith
>>> "Hello, world!".endswith("!")
True
2.5 — String Formatting (% and .format())
Expand →

Classic Formatting Methods

Before f-strings, Python used % formatting (C-style) and the .format() method. Both are still widely used in older codebases. %s = string, %d = integer, %f = float.

Python
# % formatting (C-style)
name = "John"
print("Hello, %s!" % name)

name, age = "John", 23
print("%s is %d years old." % (name, age))

# .format() method — 3 styles
txt1 = "My name is {fname}, I'm {age}".format(fname="John", age=36)
txt2 = "My name is {0}, I'm {1}".format("John", 36)   # by position
txt3 = "My name is {}, I'm {}".format("John", 36)     # auto
2.6 — Input from Console
Expand →

Reading User Input

input() pauses the program and waits for the user to type something and press Enter. It always returns a string — use int() or float() to convert if you need a number.

Python
>>> name = input("Enter your name: ")
Enter your name: Tom
>>> name
'Tom'

# Convert input to a number
age = int(input("Enter your age: "))
2.7 — f-Strings Basics Python 3.6+
Expand →

Modern String Formatting

f-strings (formatted string literals) are the modern, recommended way to format strings. Prefix the string with f and embed expressions inside {}. Any Python expression works inside the braces — variables, math, function calls.

Python
>>> website = 'Quickref.ME'
>>> f"Hello, {website}"
"Hello, Quickref.ME"

>>> num = 10
>>> f'{num} + 10 = {num + 10}'    # expressions work!
'10 + 10 = 20'

>>> f"""He said {"I'm John"}"""   # nested quotes
"He said I'm John"

>>> f'5 {"{stars}"}'              # literal { } with double braces
'5 {stars}'
2.8 — f-String Fill & Alignment
Expand →

Padding and Aligning Text

f-strings support formatting specs inside {} after a colon: {value:fill_char align width}. > = right-align, < = left-align, ^ = center. The fill character pads the remaining space.

Python
>>> f'{"text":10}'      # width 10, left-aligned (default)
'text      '
>>> f'{"test":*>10}'    # fill * from left (right-align)
'******test'
>>> f'{"test":*<10}'    # fill * from right (left-align)
'test******'
>>> f'{"test":*^10}'    # fill * both sides (center)
'***test***'
>>> f'{12345:0>10}'     # zero-pad a number
'0000012345'
2.9 — f-String Type Formatting (b, o, x, e, c)
Expand →

Number Base & Notation Formatting

f-strings can format numbers in different bases and notations by adding a type character after the colon. Add # to include the base prefix (0b, 0o, 0x).

Python
>>> f'{10:b}'           # binary
'1010'
>>> f'{10:o}'           # octal
'12'
>>> f'{200:x}'          # hexadecimal (lowercase)
'c8'
>>> f'{200:X}'          # hexadecimal (uppercase)
'C8'
>>> f'{345600000000:e}' # scientific notation
'3.456000e+11'
>>> f'{65:c}'           # character (ASCII 65 = 'A')
'A'
>>> f'{10:#b}'          # with base prefix
'0b1010'
2.10 — f-String Advanced (precision, grouping, sign, %)
Expand →

Precision, Grouping & Sign Formatting

Control decimal precision with .Nf, add thousands separator with , or _, show percentage with %, and control sign display with +.

Python
import math
f'{math.pi:.2f}'       # => '3.14'  (2 decimal places)
f'{1000000:,.2f}'      # => '1,000,000.00' (comma grouping)
f'{1000000:_.2f}'      # => '1_000_000.00' (underscore grouping)
f'{0.25:0%}'           # => '25.000000%'
f'{0.25:.0%}'          # => '25%'

# Sign control
f'{12345:+}'           # => '+12345'
f'{-12345:+}'          # => '-12345'
f'{-12345:010}'        # => '-000012345' (zero-pad negative)
03
Module 3 — Lists
Define, generate, append, slice, remove, access, sort, count, repeat
0% · 0/9 done
3.1 — Defining Lists
Expand →

Creating Lists

A list is ordered, mutable, and allows duplicates. Define with square brackets [] or list(). Lists can hold mixed types.

Python
li1 = []                       # empty list
li2 = [4, 5, 6]               # list of ints
li3 = list((1, 2, 3))          # from tuple
li4 = list(range(1, 11))        # [1,2,3,4,5,6,7,8,9,10]
list1 = ["apple", "banana", "cherry"]
list2 = [True, False, False]    # mixed types allowed
3.2 — Generating Lists (Comprehensions, filter, lambda)
Expand →

List Comprehensions & Functional Tools

List comprehensions are a concise, Pythonic way to create lists. Syntax: [expression for item in iterable if condition]. Alternatively, use filter() with a lambda function for functional-style filtering.

Python
# filter with lambda — keep only odd numbers
list(filter(lambda x : x % 2 == 1, range(1, 20)))
# => [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]

# List comprehension — squares of odd numbers
[x ** 2 for x in range(1, 11) if x % 2 == 1]
# => [1, 9, 25, 49, 81]

# Filter by condition — keep items > 5
[x for x in [3, 4, 5, 6, 7] if x > 5]
# => [6, 7]
3.3 — Appending to Lists
Expand →

Adding Items

.append(item) adds a single item to the end of a list. It modifies the list in-place and returns None.

Python
li = []
li.append(1)   # li => [1]
li.append(2)   # li => [1, 2]
li.append(4)   # li => [1, 2, 4]
li.append(3)   # li => [1, 2, 4, 3]
3.4 — List Slicing
Expand →

Extracting Sub-lists

List slicing works exactly like string slicing: list[start:end:step]. Returns a new list — does not modify the original. Omitting indices uses start of list / end of list.

Python
a = ['spam', 'egg', 'bacon', 'tomato', 'ham', 'lobster']

a[2:5]        # => ['bacon', 'tomato', 'ham']
a[-5:-2]      # => ['egg', 'bacon', 'tomato']
a[:4]         # => ['spam', 'egg', 'bacon', 'tomato']
a[2:]         # => ['bacon', 'tomato', 'ham', 'lobster']
a[:]           # => full copy of list

# With stride
a[0:6:2]      # => ['spam', 'bacon', 'ham']  (every 2nd)
a[::-1]        # => reversed list
3.5 — Removing Items (pop & del)
Expand →

Deleting Elements

.pop() removes and returns the last item (or item at given index). del list[index] deletes by index without returning. .remove(value) deletes the first occurrence of a value.

Python
li = ['bread', 'butter', 'milk']
li.pop()           # returns 'milk', li => ['bread', 'butter']
del li[0]          # deletes 'bread', li => ['butter']
3.6 — Accessing Elements
Expand →

Reading Elements by Index

Access items with square bracket notation. Indices start at 0. Use negative indices to count from the end. Accessing an out-of-range index raises an IndexError.

Python
li = ['a', 'b', 'c', 'd']
li[0]    # => 'a'   (first element)
li[-1]   # => 'd'   (last element)
li[4]    # => IndexError: list index out of range!
3.7 — Concatenating & Extending Lists
Expand →

Combining Lists

.extend(other) adds all items from another list to the end (modifies in-place). The + operator creates a new combined list without modifying the originals.

Python
odd = [1, 3, 5]
odd.extend([9, 11, 13])  # modifies odd in-place
# odd => [1, 3, 5, 9, 11, 13]

odd = [1, 3, 5]
result = odd + [9, 11, 13]  # creates new list
# result => [1, 3, 5, 9, 11, 13], odd unchanged
3.8 — Sort, Reverse & Count
Expand →

Organizing List Data

.sort() sorts the list in-place (ascending by default). .reverse() reverses in-place. .count(value) counts how many times a value appears.

Python
li = [3, 1, 3, 2, 5]
li.sort()           # li => [1, 2, 3, 3, 5]
li.reverse()        # li => [5, 3, 3, 2, 1]
li.count(3)         # => 2  (3 appears twice)
3.9 — Repeating & Other Built-in Types (Tuple, Set, Dict)
Expand →

More Collection Types

Repeating a list with * creates a new list with repeated elements. Tuples are immutable lists. Sets store unique items only. Dictionaries store key-value pairs.

Python
# Repeat
li = ["re"] * 3           # => ['re', 're', 're']

# Tuple — immutable (can't change after creation)
my_tuple = (1, 2, 3)

# Set — unique items, unordered
set1 = {"a", "b", "c"}    # duplicates auto-removed

# Dictionary — key: value pairs
a = {"one": 1, "two": 2}
a["one"]               # => 1
a.keys()               # => dict_keys(['one', 'two'])
a.values()             # => dict_values([1, 2])
a.update({"three": 3}) # add a new key-value pair
04
Module 4 — Flow Control
if, elif, else, ternary, logical operators
0% · 0/3 done
4.1 — if / elif / else
Expand →

Multi-branch Conditionals

Python uses indentation to define blocks — no curly braces. elif is Python's "else if". Only the first matching branch runs. Comparison operators: ==, !=, <, >, <=, >=. Logical: and, or, not.

Python
num = 5
if num > 10:
    print("num is totally bigger than 10.")
elif num < 10:
    print("num is smaller than 10.")  # ← this runs
else:
    print("num is indeed 10.")
4.2 — One-line Ternary if
Expand →

Inline Conditional Expression

Python's ternary expression: value_if_true if condition else value_if_false. Unlike C/C++, Python uses English words instead of ? and :.

Python
a, b = 330, 200
r = "a" if a > b else "b"
print(r)   # => "a"  (since 330 > 200 is True)
4.3 — Logical Operators (not, is, None)
Expand →

Advanced Condition Checks

not negates a boolean. is checks identity (same object), not equality. is None is the correct way to check for null/nothing in Python (not == None).

Python
value = True
if not value:
    print("Value is False")
elif value is None:          # 'is' checks identity
    print("Value is None")
else:
    print("Value is True")  # ← this runs
05
Module 5 — Loops
for, while, enumerate, break, continue, range, zip, for/else
0% · 0/7 done
5.1 — Basic for Loop
Expand →

Iterating Over Sequences

Python's for loop iterates over any iterable (list, string, range, tuple, dict, etc.). At each iteration, the loop variable is assigned the current item.

Python
primes = [2, 3, 5, 7]
for prime in primes:
    print(prime)
# Prints: 2  3  5  7
5.2 — enumerate() — Loop with Index
Expand →

Getting Index and Value Together

enumerate() wraps an iterable and returns (index, value) pairs. Perfect when you need both the position and the item. Use tuple unpacking: for i, value in enumerate(...).

Python
animals = ["dog", "cat", "mouse"]
for i, value in enumerate(animals):
    print(i, value)
# Prints:
# 0 dog
# 1 cat
# 2 mouse
5.3 — while Loop
Expand →

Condition-Controlled Loop

A while loop runs as long as its condition is True. Always ensure the condition eventually becomes False — or use break — to avoid infinite loops.

Python
x = 0
while x < 4:
    print(x)
    x += 1   # Shorthand for x = x + 1
# Prints: 0  1  2  3
5.4 — break & continue
Expand →

Loop Control Statements

break exits the loop immediately. continue skips the rest of the current iteration and moves to the next one.

1break — stop at index 5
Python
x = 0
for index in range(10):
    x = index * 10
    if index == 5:
        break   # exits loop when index is 5
    print(x)
# Prints: 0  10  20  30  40
2continue — skip index 5
Python
for index in range(3, 8):
    x = index * 10
    if index == 5:
        continue  # skips print when index is 5
    print(x)
# Prints: 30  40  60  70  (50 is skipped)
5.5 — range()
Expand →

Generating Number Sequences

range(stop), range(start, stop), or range(start, stop, step) generates a lazy sequence of integers. The stop value is exclusive.

Python
for i in range(4):
    print(i)   # Prints: 0  1  2  3

for i in range(4, 8):
    print(i)   # Prints: 4  5  6  7

for i in range(4, 10, 2):
    print(i)   # Prints: 4  6  8  (step of 2)
5.6 — zip() — Iterate Multiple Sequences
Expand →

Pairing Two Sequences

zip() combines two or more iterables element-by-element, producing tuples. Stops at the shortest iterable. Great for pairing related data.

Python
words = ['Mon', 'Tue', 'Wed']
nums  = [1, 2, 3]

for w, n in zip(words, nums):
    print('%d:%s, ' %(n, w))
# Prints: 1:Mon,  2:Tue,  3:Wed,
5.7 — for / else
Expand →

Loop's else Clause

Python's for (and while) loop can have an else block. It runs only if the loop finished without hitting a break. Very useful for search patterns: did we find what we were looking for?

Python
nums = [60, 70, 30, 110, 90]
for n in nums:
    if n > 100:
        print("%d is bigger than 100" %n)
        break      # found — skip else
else:
    print("Not found!")  # only runs if no break
# Prints: 110 is bigger than 100
06
Module 6 — Functions
def, return, *args, **kwargs, default values, lambda
0% · 0/7 done
6.1 — Basic Function Definition
Expand →

Defining Reusable Code

Use def to define a function. The function body is indented. Call it by name with (). Functions without a return statement implicitly return None.

Python
def hello_world():
    print('Hello, World!')

hello_world()   # => Hello, World!
6.2 — Arguments & Return Values
Expand →

Passing Data In and Out

Functions accept parameters (inputs) and use return to send a value back. The function stops executing when it hits return.

Python
def add(x, y):
    print("x is %s, y is %s" %(x, y))
    return x + y

add(5, 6)    # => prints "x is 5, y is 6", returns 11
6.3 — *args — Variable Positional Arguments
Expand →

Accept Any Number of Arguments

*args collects all extra positional arguments into a tuple. The name args is a convention — the * is what matters. Use when the number of inputs isn't known ahead of time.

Python
def varargs(*args):
    return args           # args is a tuple

varargs(1, 2, 3)        # => (1, 2, 3)
6.4 — **kwargs — Keyword Arguments
Expand →

Named Variable Arguments

**kwargs collects all extra keyword arguments into a dictionary. The ** is what matters. Use when you want to accept named parameters without defining them all upfront.

Python
def keyword_args(**kwargs):
    return kwargs         # kwargs is a dict

keyword_args(big="foot", loch="ness")
# => {"big": "foot", "loch": "ness"}
6.5 — Returning Multiple Values
Expand →

Tuple Unpacking as Return

Python functions can return multiple values by separating them with commas — Python packs them into a tuple. Use tuple unpacking to assign them to individual variables.

Python
def swap(x, y):
    return y, x    # returns a tuple (y, x)

x = 1; y = 2
x, y = swap(x, y)  # unpack tuple into x and y
# x => 2, y => 1
6.6 — Default Parameter Values
Expand →

Optional Arguments with Defaults

Parameters can have default values, making them optional. If the caller doesn't provide them, the default is used. Default parameters must come after non-default ones.

Python
def add(x, y=10):    # y defaults to 10 if not provided
    return x + y

add(5)       # => 15  (y uses default: 10)
add(5, 20)   # => 25  (y is 20, overrides default)
6.7 — Lambda (Anonymous Functions)
Expand →

One-line Inline Functions

A lambda is an anonymous (unnamed) function defined in a single line: lambda parameters: expression. Used for short, throwaway functions — often passed to map(), filter(), or sorted().

Python
# Is x greater than 2?
(lambda x: x > 2)(3)          # => True

# x² + y²
(lambda x, y: x ** 2 + y ** 2)(2, 1)  # => 5

# Assign to a variable for reuse
square = lambda x: x ** 2
square(4)   # => 16
07
Module 7 — Modules
import, from...import, aliases, dir(), standard library
0% · 0/4 done
7.1 — Importing Modules
Expand →

Using External Code Libraries

Python comes with a massive standard library. Use import module_name to load it, then access its functions with module.function() dot notation.

Python
import math
print(math.sqrt(16))   # => 4.0
7.2 — from...import & import *
Expand →

Selective & Wildcard Imports

from module import name imports specific items directly into your namespace — no module prefix needed. import * imports everything (not recommended for large projects as it pollutes the namespace).

Python
from math import ceil, floor
print(ceil(3.7))    # => 4  (no math. prefix needed)
print(floor(3.7))   # => 3

from math import *   # imports everything — use cautiously
7.3 — Module Aliases (import as)
Expand →

Renaming for Convenience

Use import module as alias to give a module a shorter name. Industry standard aliases: numpy as np, pandas as pd, matplotlib.pyplot as plt.

Python
import math as m

math.sqrt(16) == m.sqrt(16)  # => True (both work)
7.4 — dir() — Explore Module Contents
Expand →

Discovering What's Available

dir(module) returns a list of all attributes, functions, and constants in a module. Great for exploring unfamiliar libraries in the interactive shell.

Python
import math
dir(math)
# => ['__doc__', '__name__', 'acos', 'acosh', 'asin', ...]
# Shows all functions and constants available in math
08
Module 8 — File Handling
read, write, JSON objects, delete files and folders
0% · 0/6 done
8.1 — Reading Files (Line by Line)
Expand →

Opening and Reading Files

Use with open(filename) — the with statement automatically closes the file when done, even if an error occurs. Mode 'r' = read (default). Iterate line by line with a for loop. enumerate() adds a line number.

Python
# Simple line-by-line read
with open("myfile.txt") as file:
    for line in file:
        print(line)

# With line numbers
file = open('myfile.txt', 'r')
for i, line in enumerate(file, start=1):
    print("Number %s: %s" % (i, line))
8.2 — Writing Strings to Files
Expand →

Writing & Reading Text

Mode 'w+' opens for writing AND reading (creates file if it doesn't exist, overwrites if it does). file.write() writes a string. file.read() reads the entire file as one string.

Python
# Write
contents = {"aa": 12, "bb": 21}
with open("myfile1.txt", "w+") as file:
    file.write(str(contents))   # writes dict as string

# Read back
with open('myfile1.txt', "r+") as file:
    contents = file.read()
print(contents)
8.3 — Writing/Reading JSON Objects
Expand →

Serializing Python Objects to JSON

The json module converts Python dicts/lists to JSON strings (json.dumps()) and writes them to files, and reads JSON back into Python objects (json.load()). JSON is the universal data exchange format.

Python
import json

# Write object to file as JSON
contents = {"aa": 12, "bb": 21}
with open("myfile2.txt", "w+") as file:
    file.write(json.dumps(contents))   # serialize to JSON string

# Read JSON back into Python object
with open('myfile2.txt', "r+") as file:
    contents = json.load(file)         # deserialize from JSON
print(contents)  # => {'aa': 12, 'bb': 21}
8.4 — Deleting Files (os.remove)
Expand →

Removing Files with os

The os module provides operating system functions. os.remove() deletes a file. Always check if it exists first with os.path.exists() to avoid errors.

Python
import os

# Delete directly (raises error if file doesn't exist)
os.remove("myfile.txt")

# Safe deletion: check first
if os.path.exists("myfile.txt"):
    os.remove("myfile.txt")
else:
    print("The file does not exist")
8.5 — Deleting Folders
Expand →

Removing Directories

os.rmdir() removes an empty directory. For non-empty directories (with files inside), use shutil.rmtree().

Python
import os
os.rmdir("myfolder")    # only works if folder is empty

# For non-empty folders:
import shutil
shutil.rmtree("myfolder")  # removes folder and all contents
8.6 — Advanced Data Types: Heaps, Stacks & Queues
Expand →

Python's Advanced Collections

heapq provides a min-heap (priority queue). collections.deque is a double-ended queue with O(1) append/pop from both sides — used as both a stack (LIFO) and queue (FIFO).

1Heaps — min-heap via heapqAdvanced
Python
import heapq

myList = [9, 5, 4, 1, 3, 2]
heapq.heapify(myList)      # convert to min-heap in-place O(n)
print(myList)              # => [1, 3, 2, 5, 9, 4]
print(myList[0])           # => 1 (smallest always at index 0)

heapq.heappush(myList, 10) # insert 10 O(log n)
x = heapq.heappop(myList)  # pop smallest O(log n)
print(x)                   # => 1

# Max-heap trick: negate all values
myList = [-val for val in [9, 5, 4, 1, 3, 2]]
heapq.heapify(myList)
x = heapq.heappop(myList)
print(-x)                  # => 9 (largest)
2Deque — double-ended queueAdvanced
Python
from collections import deque

q = deque([1, 2, 3])
q.append(4)       # append to right  → deque([1,2,3,4])
q.appendleft(0)   # append to left   → deque([0,1,2,3,4])
x = q.pop()        # remove from right → x=4
y = q.popleft()    # remove from left  → y=0
q.rotate(1)        # rotate 1 step right → deque([3,1,2])
09
Module 9 — Classes & Inheritance
OOP: class, __init__, methods, class vars, super, repr, polymorphism, inheritance
0% · 0/8 done
9.1 — Defining a Class & Instantiation
Expand →

Classes are Blueprints

A class is a template for creating objects. Instantiation creates an actual object from that template. pass is a no-op placeholder when you want an empty class body.

Python
class MyNewClass:
    pass   # empty class body — valid Python

my = MyNewClass()   # Class Instantiation — creates an object
9.2 — Constructors (__init__)
Expand →

Initializing Objects

__init__ is Python's constructor — called automatically when an object is created. self refers to the instance being created. Use it to set instance attributes (data specific to each object).

Python
class Animal:
    def __init__(self, voice):
        self.voice = voice   # instance attribute

cat = Animal('Meow')
print(cat.voice)    # => Meow

dog = Animal('Woof')
print(dog.voice)    # => Woof
9.3 — Instance Methods
Expand →

Functions Attached to Objects

A method is a function defined inside a class. The first parameter is always self (the instance calling the method). Call methods with dot notation: object.method().

Python
class Dog:
    def bark(self):           # self is required
        print("Ham-Ham")

charlie = Dog()
charlie.bark()   # => "Ham-Ham"
9.4 — Class Variables
Expand →

Shared Data Across All Instances

Class variables are defined directly in the class body (not inside __init__). They are shared by all instances — accessible via the class name or any instance.

Python
class MyClass:
    class_variable = "A class variable!"  # shared by all

print(MyClass.class_variable)  # => A class variable!

x = MyClass()
print(x.class_variable)       # => A class variable! (also works)
9.5 — super() Function
Expand →

Calling the Parent Class

super() gives access to the parent class's methods from inside a child class. Used to extend (not replace) the parent's behavior. Essential when overriding methods.

Python
class ParentClass:
    def print_test(self):
        print("Parent Method")

class ChildClass(ParentClass):
    def print_test(self):
        print("Child Method")
        super().print_test()  # calls parent's version

child = ChildClass()
child.print_test()
# Prints:
# Child Method
# Parent Method
9.6 — __repr__ Method & Custom Exceptions
Expand →

String Representation & Custom Errors

__repr__ defines how your object is represented as a string (when printed). Custom exceptions extend Exception — useful for domain-specific error handling in your application.

Python
class Employee:
    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return self.name   # what print() shows

john = Employee('John')
print(john)   # => John  (uses __repr__)

# Custom exception
class CustomError(Exception):
    pass   # raise CustomError("something went wrong")
9.7 — Polymorphism & Method Overriding
Expand →

Same Interface, Different Behavior

Polymorphism: different classes can have methods with the same name, each behaving differently. Overriding: a child class replaces a parent method with its own version. Python always uses the most specific (child) version available.

Python
class ParentClass:
    def print_self(self): print('A')

class ChildClass(ParentClass):
    def print_self(self): print('B')  # overrides parent

obj_A = ParentClass()
obj_B = ChildClass()

obj_A.print_self()   # => A
obj_B.print_self()   # => B  (child's version used)
9.8 — Inheritance
Expand →

Child Classes Extend Parents

Inheritance lets a class inherit all attributes and methods of a parent. The child can add its own methods and override inherited ones. Python uses class Child(Parent): syntax.

Python
class Animal:
    def __init__(self, name, legs):
        self.name = name
        self.legs = legs

class Dog(Animal):             # Dog inherits from Animal
    def sound(self):
        print("Woof!")

Yoki = Dog("Yoki", 4)
print(Yoki.name)    # => Yoki  (inherited attribute)
print(Yoki.legs)    # => 4     (inherited attribute)
Yoki.sound()        # => Woof! (Dog's own method)
10
Module 10 — Advanced / Miscellaneous
Comments, generators, exception handling (try/except/finally)
0% · 0/4 done
10.1 — Comments (Single & Multiline)
Expand →

Documenting Your Code

Python uses # for single-line comments. Triple-quoted strings ("""...""" or '''...''') are used as multi-line comments and docstrings (documentation). Docstrings placed right after a def or class are accessible via help().

Python
# This is a single-line comment.

""" Multiline strings can be written
    using three "s, and are often used
    as documentation.
"""

''' Multiline strings can also use
    three single quotes — same effect.
'''
10.2 — Generators (yield)
Expand →

Lazy Evaluation — Memory Efficient

A generator is a function that uses yield instead of return. It produces values one at a time, on demand — never stores all values in memory. Perfect for large datasets or infinite sequences.

Python
def double_numbers(iterable):
    for i in iterable:
        yield i + i     # yields one value at a time (lazy)

# Generator expressions (one-liner)
values = (-x for x in [1, 2, 3, 4, 5])
gen_to_list = list(values)
print(gen_to_list)  # => [-1, -2, -3, -4, -5]

Use () for generator expressions and [] for list comprehensions. Generator expressions use zero extra memory — they produce values on demand. Convert with list() only when you need all values at once.

10.3 — Exception Handling (try / except / else / finally)
Expand →

Graceful Error Handling

Use try/except to catch and handle errors without crashing. raise manually triggers an exception. else runs only if no exception occurred. finally always runs — perfect for cleanup (closing files, releasing resources).

Python
try:
    raise IndexError("This is an index error")  # manually raise

except IndexError as e:
    pass    # handle IndexError — do recovery here

except (TypeError, NameError):
    pass    # handle multiple exception types at once

else:
    print("All good!")    # only runs if try had NO exception

finally:
    print("We can clean up resources here")
    # ALWAYS runs — exception or not

Best practice: catch specific exception types, not bare except:. Bare except catches everything including keyboard interrupts and system exits, making bugs very hard to find.

10.4 — File Handling Quick Reference
Expand →

File Open Modes Cheatsheet

Quick reference for all file opening modes and when to use them.

ModeMeaningCreates?Overwrites?
'r'Read onlyNoNo
'w'Write onlyYesYes
'a'AppendYesNo (adds to end)
'r+'Read + WriteNoNo
'w+'Write + ReadYesYes
'b'Binary mode suffix

Always use the with statement when working with files — it guarantees the file is properly closed even if an exception occurs. Never rely on the garbage collector to close files.