Python Tutorial
Master the most versatile programming language from basics to advanced
1 What is Python?
Python is a high-level, interpreted programming language known for its simplicity and readability. Created by Guido van Rossum in 1991, it's one of the most popular languages for web development, data science, AI/ML, automation, and more.
🔑 Why Learn Python?
Easy to Learn: Clean, readable syntax that's beginner-friendly
Versatile: Used in web, data science, AI, automation, and more
Large Community: Extensive libraries and active support
High Demand: One of the most sought-after programming skills
Python vs Other Languages
# Python - Simple and readable def greet(name): return f"Hello, {name}!" print(greet("World")) # Output: Hello, World!
// Java - More verbose public class Main { public static String greet(String name) { return "Hello, " + name + "!"; } public static void main(String[] args) { System.out.println(greet("World")); } }
2 Installation & Setup
Python can be installed from python.org or through package managers. Most systems come with Python pre-installed.
# Check if Python is installed python --version # or python3 --version # Install on Ubuntu/Debian sudo apt update sudo apt install python3 python3-pip # Install on macOS (using Homebrew) brew install python3 # Install on Windows # Download from python.org and run installer # Make sure to check "Add Python to PATH" # Create a virtual environment (recommended) python3 -m venv myproject source myproject/bin/activate # Linux/Mac myproject\Scripts\activate # Windows # Install packages with pip pip install numpy pandas requests
💡 IDEs for Python
VS Code - Free, lightweight, great extensions
PyCharm - Full-featured Python IDE
Jupyter Notebook - Interactive coding for data science
IDLE - Comes with Python installation
3 Your First Python Program
Let's write your first Python program! Create a file called hello.py and add the following code.
# This is a comment - Python ignores it print("Hello, World!") # Variables don't need type declarations name = "Alice" age = 25 # f-strings for string formatting print(f"My name is {name} and I am {age} years old.") # Simple math result = 10 + 5 * 2 print(f"10 + 5 * 2 = {result}")
# Run from terminal python hello.py # Or use interactive mode python >>> print("Hello!") Hello! >>> exit()
4 Variables & Data Types
Python is dynamically typed - you don't need to declare variable types. Python figures it out automatically.
# Numbers age = 25 # int price = 19.99 # float big_num = 1_000_000 # underscores for readability # Strings name = "Alice" message = 'Hello, World!' multi_line = """This is a multi-line string""" # Boolean is_active = True is_logged_in = False # None (null value) result = None # Check types print(type(age)) # <class 'int'> print(type(price)) # <class 'float'> print(type(name)) # <class 'str'> print(type(is_active)) # <class 'bool'> # Type conversion num_str = "42" num_int = int(num_str) # String to int num_float = float(num_str) # String to float back_to_str = str(42) # Int to string # Multiple assignment x, y, z = 1, 2, 3 a = b = c = 0
⚠️ Variable Naming Rules
• Must start with letter or underscore
• Can contain letters, numbers, underscores
• Case-sensitive (age ≠ Age ≠ AGE)
• Cannot use reserved words (if, for, class, etc.)
5 Operators
Python supports various operators for arithmetic, comparison, logical operations, and more.
# Arithmetic Operators a, b = 10, 3 print(a + b) # 13 (Addition) print(a - b) # 7 (Subtraction) print(a * b) # 30 (Multiplication) print(a / b) # 3.333... (Division - always float) print(a // b) # 3 (Floor Division - integer) print(a % b) # 1 (Modulus - remainder) print(a ** b) # 1000 (Exponent - 10^3) # Comparison Operators x, y = 5, 10 print(x == y) # False (Equal) print(x != y) # True (Not equal) print(x < y) # True (Less than) print(x > y) # False (Greater than) print(x <= y) # True (Less than or equal) print(x >= y) # False (Greater than or equal) # Logical Operators print(True and False) # False print(True or False) # True print(not True) # False # Assignment Operators n = 10 n += 5 # n = n + 5 → 15 n -= 3 # n = n - 3 → 12 n *= 2 # n = n * 2 → 24 n //= 4 # n = n // 4 → 6 # Identity Operators a = [1, 2, 3] b = [1, 2, 3] c = a print(a == b) # True (same values) print(a is b) # False (different objects) print(a is c) # True (same object) # Membership Operators fruits = ["apple", "banana", "cherry"] print("apple" in fruits) # True print("grape" not in fruits) # True
6 Strings
Strings in Python are immutable sequences of characters. Python provides powerful string manipulation methods.
# String creation single = 'Hello' double = "World" multi = """Multi line string""" # String concatenation full = single + " " + double # "Hello World" # String formatting name = "Alice" age = 25 # f-strings (recommended - Python 3.6+) msg1 = f"Name: {name}, Age: {age}" # .format() method msg2 = "Name: {}, Age: {}".format(name, age) # % operator (old style) msg3 = "Name: %s, Age: %d" % (name, age) # String indexing & slicing text = "Python" print(text[0]) # 'P' (first character) print(text[-1]) # 'n' (last character) print(text[0:3]) # 'Pyt' (slice) print(text[::2]) # 'Pto' (every 2nd char) print(text[::-1]) # 'nohtyP' (reversed) # String methods s = " Hello, World! " print(s.strip()) # "Hello, World!" (remove whitespace) print(s.lower()) # " hello, world! " print(s.upper()) # " HELLO, WORLD! " print(s.replace("World", "Python")) # " Hello, Python! " print(s.split(",")) # [' Hello', ' World! '] print(" ".join(["a", "b", "c"])) # "a b c" # String checks print("hello".startswith("he")) # True print("hello".endswith("lo")) # True print("123".isdigit()) # True print("abc".isalpha()) # True print("hello".find("ll")) # 2 (index of substring)
7 Input & Output
Python uses print() for output and input() for user input.
# Basic print print("Hello, World!") # Print with multiple arguments print("Name:", "Alice", "Age:", 25) # Output: Name: Alice Age: 25 # Print with custom separator and end print("A", "B", "C", sep="-") # A-B-C print("Hello", end=" ") # No newline print("World") # Hello World # User input (always returns string) name = input("Enter your name: ") print(f"Hello, {name}!") # Input with type conversion age = int(input("Enter your age: ")) price = float(input("Enter price: ")) # Simple calculator example num1 = float(input("First number: ")) num2 = float(input("Second number: ")) print(f"Sum: {num1 + num2}") print(f"Product: {num1 * num2}")
8 If-Else Statements
Python uses if, elif, and else for conditional execution. Indentation defines code blocks.
# Basic if-else age = 18 if age >= 18: print("You are an adult") else: print("You are a minor") # if-elif-else chain score = 85 if score >= 90: grade = "A" elif score >= 80: grade = "B" elif score >= 70: grade = "C" elif score >= 60: grade = "D" else: grade = "F" print(f"Grade: {grade}") # Grade: B # Nested conditions num = 15 if num > 0: if num % 2 == 0: print("Positive and even") else: print("Positive and odd") else: print("Not positive") # Ternary operator (one-liner) status = "Adult" if age >= 18 else "Minor" print(status) # Multiple conditions x = 5 if 0 < x < 10: # Python allows chaining print("x is between 0 and 10") # Truthy and Falsy values # Falsy: None, 0, "", [], {}, set(), False # Everything else is truthy name = "" if name: print(f"Hello, {name}") else: print("Name is empty")
⚠️ Indentation Matters!
Python uses indentation (4 spaces recommended) to define code blocks. Incorrect indentation causes IndentationError. Always be consistent!
9 Loops
Python provides for and while loops for iteration.
# For loop with range for i in range(5): print(i) # 0, 1, 2, 3, 4 # range(start, stop, step) for i in range(1, 10, 2): print(i) # 1, 3, 5, 7, 9 # For loop with list fruits = ["apple", "banana", "cherry"] for fruit in fruits: print(fruit) # enumerate() - get index and value for index, fruit in enumerate(fruits): print(f"{index}: {fruit}") # 0: apple, 1: banana, 2: cherry # Loop through string for char in "Python": print(char, end=" ") # P y t h o n # While loop count = 0 while count < 5: print(count) count += 1 # break - exit loop for i in range(10): if i == 5: break print(i) # 0, 1, 2, 3, 4 # continue - skip iteration for i in range(5): if i == 2: continue print(i) # 0, 1, 3, 4 (skips 2) # else clause (runs if loop completes normally) for i in range(3): print(i) else: print("Loop finished!")
10 Comprehensions
Comprehensions are a concise way to create lists, dictionaries, and sets in Python.
# List comprehension # Traditional way squares = [] for x in range(5): squares.append(x ** 2) # Comprehension way squares = [x ** 2 for x in range(5)] print(squares) # [0, 1, 4, 9, 16] # With condition evens = [x for x in range(10) if x % 2 == 0] print(evens) # [0, 2, 4, 6, 8] # If-else in comprehension labels = ["even" if x % 2 == 0 else "odd" for x in range(5)] print(labels) # ['even', 'odd', 'even', 'odd', 'even'] # Nested comprehension matrix = [[j for j in range(3)] for i in range(3)] print(matrix) # [[0,1,2], [0,1,2], [0,1,2]] # Dictionary comprehension squares_dict = {x: x**2 for x in range(5)} print(squares_dict) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} # Set comprehension unique_lengths = {len(word) for word in ["hello", "world", "hi"]} print(unique_lengths) # {2, 5} # Generator expression (memory efficient) gen = (x ** 2 for x in range(1000000)) print(next(gen)) # 0 print(next(gen)) # 1
💡 When to Use Comprehensions
Use comprehensions for simple transformations and filtering. For complex logic with multiple statements, stick to regular loops for better readability.
11 Lists
Lists are mutable, ordered collections that can hold items of different types.
# Creating lists numbers = [1, 2, 3, 4, 5] mixed = [1, "hello", 3.14, True] empty = [] from_range = list(range(5)) # [0, 1, 2, 3, 4] # Accessing elements print(numbers[0]) # 1 (first) print(numbers[-1]) # 5 (last) print(numbers[1:4]) # [2, 3, 4] (slice) # Modifying lists numbers[0] = 10 # [10, 2, 3, 4, 5] numbers.append(6) # Add to end numbers.insert(0, 0) # Insert at index numbers.extend([7, 8]) # Add multiple # Removing elements numbers.remove(3) # Remove by value popped = numbers.pop() # Remove & return last popped = numbers.pop(0) # Remove & return at index del numbers[0] # Delete by index numbers.clear() # Remove all # List methods nums = [3, 1, 4, 1, 5, 9, 2, 6] print(len(nums)) # 8 print(nums.count(1)) # 2 print(nums.index(5)) # 4 print(min(nums)) # 1 print(max(nums)) # 9 print(sum(nums)) # 31 # Sorting nums.sort() # In-place sort nums.sort(reverse=True) # Descending sorted_nums = sorted(nums) # Returns new list nums.reverse() # Reverse in-place # Copying lists original = [1, 2, 3] copy1 = original.copy() # Shallow copy copy2 = list(original) # Shallow copy copy3 = original[:] # Shallow copy # List unpacking a, b, c = [1, 2, 3] first, *rest = [1, 2, 3, 4] # first=1, rest=[2,3,4]
12 Tuples
Tuples are immutable sequences. Once created, they cannot be modified.
# Creating tuples point = (10, 20) single = (42,) # Note the comma! from_list = tuple([1, 2, 3]) without_parens = 1, 2, 3 # Also a tuple # Accessing elements print(point[0]) # 10 print(point[-1]) # 20 print(point[0:1]) # (10,) # Tuples are immutable! # point[0] = 5 # TypeError! # Tuple unpacking x, y = point print(f"x={x}, y={y}") # x=10, y=20 # Swap variables a, b = 1, 2 a, b = b, a print(a, b) # 2, 1 # Tuple methods nums = (1, 2, 2, 3) print(nums.count(2)) # 2 print(nums.index(3)) # 3 # Named tuples (more readable) from collections import namedtuple Point = namedtuple('Point', ['x', 'y']) p = Point(10, 20) print(p.x, p.y) # 10, 20 # Why use tuples? # - Faster than lists # - Can be used as dictionary keys # - Protect data from modification # - Indicate "this data shouldn't change"
13 Dictionaries
Dictionaries store key-value pairs. They're unordered (Python 3.7+ maintains insertion order), mutable, and extremely fast for lookups.
# Creating dictionaries person = { "name": "Alice", "age": 25, "city": "NYC" } empty = {} from_pairs = dict([("a", 1), ("b", 2)]) # Accessing values print(person["name"]) # "Alice" print(person.get("name")) # "Alice" print(person.get("job", "N/A")) # "N/A" (default) # Modifying dictionaries person["age"] = 26 # Update value person["email"] = "a@b.com" # Add new key person.update({"job": "Dev"}) # Update multiple # Removing elements del person["city"] # Delete key age = person.pop("age") # Remove & return person.clear() # Remove all # Dictionary methods user = {"name": "Bob", "age": 30} print(user.keys()) # dict_keys(['name', 'age']) print(user.values()) # dict_values(['Bob', 30]) print(user.items()) # dict_items([('name','Bob'),...]) # Looping through dictionaries for key in user: print(key, user[key]) for key, value in user.items(): print(f"{key}: {value}") # Check if key exists if "name" in user: print("Name exists") # Nested dictionaries users = { "user1": {"name": "Alice", "age": 25}, "user2": {"name": "Bob", "age": 30} } print(users["user1"]["name"]) # "Alice"
14 Sets
Sets are unordered collections of unique elements. They're perfect for removing duplicates and mathematical set operations.
# Creating sets fruits = {"apple", "banana", "cherry"} from_list = set([1, 2, 2, 3]) # {1, 2, 3} empty = set() # Note: {} creates empty dict! # Remove duplicates from list nums = [1, 2, 2, 3, 3, 3] unique = list(set(nums)) # [1, 2, 3] # Adding elements fruits.add("orange") fruits.update(["mango", "grape"]) # Removing elements fruits.remove("banana") # Raises error if not found fruits.discard("kiwi") # No error if not found fruits.pop() # Remove arbitrary element # Set operations a = {1, 2, 3, 4} b = {3, 4, 5, 6} print(a | b) # Union: {1, 2, 3, 4, 5, 6} print(a & b) # Intersection: {3, 4} print(a - b) # Difference: {1, 2} print(a ^ b) # Symmetric diff: {1, 2, 5, 6} # Or use methods print(a.union(b)) print(a.intersection(b)) print(a.difference(b)) # Set comparisons print({1, 2}.issubset({1, 2, 3})) # True print({1, 2, 3}.issuperset({1, 2})) # True print({1, 2}.isdisjoint({3, 4})) # True (no common) # Frozen set (immutable) immutable = frozenset([1, 2, 3]) # immutable.add(4) # Error!
15 Functions
Functions are reusable blocks of code defined with the def keyword.
# Basic function def greet(): print("Hello, World!") greet() # Call the function # Function with parameters def greet_person(name): print(f"Hello, {name}!") greet_person("Alice") # Function with return value def add(a, b): return a + b result = add(5, 3) print(result) # 8 # Default parameters def greet(name, greeting="Hello"): return f"{greeting}, {name}!" print(greet("Alice")) # Hello, Alice! print(greet("Bob", "Hi")) # Hi, Bob! # Keyword arguments print(greet(greeting="Hey", name="Charlie")) # *args - variable positional arguments def sum_all(*args): return sum(args) print(sum_all(1, 2, 3, 4)) # 10 # **kwargs - variable keyword arguments def print_info(**kwargs): for key, value in kwargs.items(): print(f"{key}: {value}") print_info(name="Alice", age=25, city="NYC") # Multiple return values (tuple) def min_max(numbers): return min(numbers), max(numbers) minimum, maximum = min_max([3, 1, 4, 1, 5]) print(f"Min: {minimum}, Max: {maximum}") # Docstring def calculate_area(radius): """ Calculate the area of a circle. Args: radius: The radius of the circle Returns: The area of the circle """ return 3.14159 * radius ** 2
16 Lambda Functions
Lambda functions are small, anonymous functions defined with the lambda keyword.
# Basic lambda square = lambda x: x ** 2 print(square(5)) # 25 # Multiple parameters add = lambda a, b: a + b print(add(3, 4)) # 7 # Lambda with built-in functions numbers = [3, 1, 4, 1, 5, 9, 2] # sorted with key words = ["banana", "apple", "cherry"] sorted_by_len = sorted(words, key=lambda x: len(x)) print(sorted_by_len) # ['apple', 'banana', 'cherry'] # map - apply function to all items squared = list(map(lambda x: x**2, numbers)) print(squared) # [9, 1, 16, 1, 25, 81, 4] # filter - keep items that match condition evens = list(filter(lambda x: x % 2 == 0, numbers)) print(evens) # [4, 2] # reduce - accumulate values from functools import reduce product = reduce(lambda x, y: x * y, [1, 2, 3, 4]) print(product) # 24 # Sorting objects by attribute users = [ {"name": "Alice", "age": 25}, {"name": "Bob", "age": 30}, {"name": "Charlie", "age": 20} ] by_age = sorted(users, key=lambda u: u["age"]) print(by_age) # [{'name': 'Charlie', 'age': 20}, {'name': 'Alice', 'age': 25}, {'name': 'Bob', 'age': 30}]
17 Classes & Objects
Python is an object-oriented language. Classes are blueprints for creating objects.
# Basic class class Person: # Constructor def __init__(self, name, age): self.name = name # Instance attribute self.age = age # Instance method def greet(self): return f"Hello, I'm {self.name}" # String representation def __str__(self): return f"Person({self.name}, {self.age})" # Create objects alice = Person("Alice", 25) bob = Person("Bob", 30) print(alice.name) # Alice print(alice.greet()) # Hello, I'm Alice print(alice) # Person(Alice, 25) # Class with class attribute class Dog: species = "Canis familiaris" # Class attribute (shared) def __init__(self, name, breed): self.name = name # Instance attribute self.breed = breed def bark(self): return f"{self.name} says Woof!" buddy = Dog("Buddy", "Golden Retriever") print(buddy.species) # Canis familiaris print(buddy.bark()) # Buddy says Woof! # Class with private attributes class BankAccount: def __init__(self, balance): self._balance = balance # Convention: "private" self.__secret = 123 # Name mangling def deposit(self, amount): self._balance += amount def get_balance(self): return self._balance # Property decorator class Circle: def __init__(self, radius): self._radius = radius @property def radius(self): return self._radius @radius.setter def radius(self, value): if value > 0: self._radius = value @property def area(self): return 3.14159 * self._radius ** 2 c = Circle(5) print(c.area) # 78.53975 c.radius = 10 print(c.area) # 314.159
18 Inheritance
Inheritance allows a class to inherit attributes and methods from another class.
# Base class class Animal: def __init__(self, name): self.name = name def speak(self): raise NotImplementedError("Subclass must implement") def info(self): return f"I am {self.name}" # Child classes class Dog(Animal): def __init__(self, name, breed): super().__init__(name) # Call parent constructor self.breed = breed def speak(self): return f"{self.name} says Woof!" class Cat(Animal): def speak(self): return f"{self.name} says Meow!" # Using inheritance dog = Dog("Buddy", "Labrador") cat = Cat("Whiskers") print(dog.speak()) # Buddy says Woof! print(cat.speak()) # Whiskers says Meow! print(dog.info()) # I am Buddy (inherited) print(dog.breed) # Labrador # Check inheritance print(isinstance(dog, Dog)) # True print(isinstance(dog, Animal)) # True print(issubclass(Dog, Animal)) # True # Multiple inheritance class Flyable: def fly(self): return "Flying!" class Swimmable: def swim(self): return "Swimming!" class Duck(Animal, Flyable, Swimmable): def speak(self): return f"{self.name} says Quack!" duck = Duck("Donald") print(duck.speak()) # Donald says Quack! print(duck.fly()) # Flying! print(duck.swim()) # Swimming!
19 File Handling
Python makes it easy to read from and write to files using the built-in open() function.
# Writing to a file with open("example.txt", "w") as file: file.write("Hello, World!\n") file.write("This is line 2.\n") # File automatically closed after 'with' block # Reading entire file with open("example.txt", "r") as file: content = file.read() print(content) # Reading line by line with open("example.txt", "r") as file: for line in file: print(line.strip()) # Remove trailing newline # Reading into list with open("example.txt", "r") as file: lines = file.readlines() # Appending to file with open("example.txt", "a") as file: file.write("Appended line.\n") # File modes: # "r" - Read (default) # "w" - Write (overwrites) # "a" - Append # "x" - Create (fails if exists) # "b" - Binary mode (rb, wb) # "+" - Read and write (r+, w+) # Working with JSON import json data = {"name": "Alice", "age": 25} # Write JSON with open("data.json", "w") as file: json.dump(data, file, indent=2) # Read JSON with open("data.json", "r") as file: loaded = json.load(file) print(loaded["name"]) # Alice # Working with CSV import csv # Write CSV with open("users.csv", "w", newline="") as file: writer = csv.writer(file) writer.writerow(["Name", "Age"]) writer.writerow(["Alice", 25]) writer.writerow(["Bob", 30]) # Read CSV with open("users.csv", "r") as file: reader = csv.reader(file) for row in reader: print(row)
💡 Always Use with Statement
The with statement automatically closes the file when done, even if an exception occurs. This prevents resource leaks and is the recommended way to handle files.
20 Exception Handling
Exceptions are errors that occur during program execution. Python provides try-except blocks to handle them gracefully.
# Basic try-except try: result = 10 / 0 except ZeroDivisionError: print("Cannot divide by zero!") # Multiple exception types try: num = int("abc") except ValueError: print("Invalid number format") except TypeError: print("Type error occurred") # Catch multiple in one except try: # risky code pass except (ValueError, TypeError) as e: print(f"Error: {e}") # else and finally try: result = 10 / 2 except ZeroDivisionError: print("Division error") else: print(f"Result: {result}") # Runs if no exception finally: print("Always runs") # Cleanup code # Raising exceptions def validate_age(age): if age < 0: raise ValueError("Age cannot be negative") if age > 150: raise ValueError("Age too high") return True try: validate_age(-5) except ValueError as e: print(e) # Age cannot be negative # Custom exceptions class InsufficientFundsError(Exception): def __init__(self, balance, amount): self.message = f"Cannot withdraw {amount}. Balance: {balance}" super().__init__(self.message) def withdraw(balance, amount): if amount > balance: raise InsufficientFundsError(balance, amount) return balance - amount try: withdraw(100, 150) except InsufficientFundsError as e: print(e) # Cannot withdraw 150. Balance: 100
21 Modules & Packages
Modules are Python files that can be imported. Packages are directories containing modules.
# Importing modules import math print(math.pi) # 3.141592... print(math.sqrt(16)) # 4.0 # Import with alias import numpy as np import pandas as pd # Import specific items from math import pi, sqrt print(pi) # 3.141592... (no math. prefix) # Import all (avoid in production) from math import * # Common built-in modules import os print(os.getcwd()) # Current directory print(os.listdir(".")) # List directory contents import datetime now = datetime.datetime.now() print(now.strftime("%Y-%m-%d %H:%M:%S")) import random print(random.randint(1, 100)) # Random int 1-100 print(random.choice(["a", "b", "c"])) # Random choice # Creating your own module # mymodule.py: # def greet(name): # return f"Hello, {name}!" # # PI = 3.14159 # main.py: # import mymodule # print(mymodule.greet("Alice")) # print(mymodule.PI) # Package structure: # mypackage/ # __init__.py # module1.py # module2.py # subpackage/ # __init__.py # module3.py # from mypackage import module1 # from mypackage.subpackage import module3
22 Decorators
Decorators are a powerful feature that allows you to modify the behavior of functions or classes.
# Basic decorator def my_decorator(func): def wrapper(): print("Before function call") func() print("After function call") return wrapper @my_decorator def say_hello(): print("Hello!") say_hello() # Output: # Before function call # Hello! # After function call # Decorator with arguments def decorator_with_args(func): def wrapper(*args, **kwargs): print(f"Calling {func.__name__}") result = func(*args, **kwargs) print(f"{func.__name__} returned {result}") return result return wrapper @decorator_with_args def add(a, b): return a + b add(3, 5) # Calling add # add returned 8 # Timer decorator (practical example) import time def timer(func): def wrapper(*args, **kwargs): start = time.time() result = func(*args, **kwargs) end = time.time() print(f"{func.__name__} took {end - start:.4f}s") return result return wrapper @timer def slow_function(): time.sleep(1) return "Done" slow_function() # slow_function took 1.0012s # Built-in decorators class MyClass: @staticmethod def static_method(): return "No self needed" @classmethod def class_method(cls): return f"Called on {cls.__name__}" @property def my_property(self): return "Property value"
💡 Common Use Cases for Decorators
• Logging and debugging
• Performance timing
• Authentication and authorization
• Caching/memoization
• Input validation