A Comprehensive Guide to Python
Programming
1. Introduction to Python Programming
Python's Execution Process
Python is often called an interpreted language, but it's more accurate to say it's a hybrid.
Here’s how it works:
1. Compilation to Bytecode: When you run a Python script (.py file), the interpreter first
compiles the source code into a lower-level, platform-independent format called
bytecode (stored in .pyc files). This is an automatic and hidden step.
2. Interpretation by PVM: The Python Virtual Machine (PVM) then takes this bytecode
and executes it line by line.
This hybrid approach makes Python portable (bytecode can run on any system with a PVM) and
feel like an interpreted language because there's no separate, manual compilation step like in
C++ or Java.
Python Environment Setup
To start programming in Python, you need to install the Python interpreter on your computer.
1. Download Python: Go to the official Python website (python.org) and download the
latest version for your operating system (Windows, macOS, or Linux).
2. Installation: Run the installer. On Windows, make sure to check the box that says "Add
Python to PATH". This allows you to run Python from your command prompt or
terminal.
3. Verify Installation: Open a terminal or command prompt and type python --
version. If it shows the version number you installed, you're all set!
You can write Python code in a simple text editor, but it's much easier to use an Integrated
Development Environment (IDE) like VS Code, PyCharm, or Jupyter Notebook, which provide
features like syntax highlighting and debugging.
2. Python Fundamentals
Data Types in Python
1. Number Data Types
Number data types are used to store numeric values. They are immutable, which means that
changing the value of a number data type results in a newly allocated object.
There are three main numeric types in Python:
Integer
An integer is a whole number with no decimal places. For example, 1 is an integer, but 1.0 is
not. The name for the integer data type is int.
# Example
type(1)
# Output: <class 'int'>
Floating-Point (Float)
A floating-point number, or float for short, is a number that has a decimal place. For example,
1.0 and -2.75 are floating-point numbers.
# Example
type(1.0)
# Output: <class 'float'>
Complex
Complex numbers are of the form a + bJ, where a and b are floats and J (or j) represents the
square root of -1 (an imaginary number). The real part of the number is a, and the imaginary
part is b. Complex numbers are not used frequently in general Python programming.
# Example
type(1 + 2j)
# Output: <class 'complex'>
2. None Type
The None keyword is used to define a null value, or no value at all. It's important to understand
that None is not the same as 0, False, or an empty string. None is a data type of its own
(NoneType), and only None can be None.
# Example
x = None
if x:
print("Do you think None is True?")
elif x is False:
print("Do you think None is False?")
else:
print("None is not True, or False, None is just None...")
# Output: None is not True, or False, None is just None...
3. Sequence Types
Sequences allow you to store multiple values in an organized and efficient fashion. They are
ordered collections, meaning the items have a defined order, and they can be accessed by their
index.
String (str)
A string is a sequence of characters, enclosed in single, double, or triple quotes. Strings are
immutable.
# Creating a string
my_string = "Hello, Python!"
# Accessing characters by index
print(my_string[0]) # Output: H
print(my_string[7]) # Output: P
# Slicing to get a substring
print(my_string[0:5]) # Output: Hello
List (list)
A list is an ordered collection of items, enclosed in square brackets []. Lists are mutable,
meaning you can change their content (add, remove, or modify items).
# Creating a list
my_list = [1, "apple", 3.14, True]
# Accessing items by index
print(my_list[1]) # Output: apple
# Modifying an item
my_list[0] = "one"
print(my_list) # Output: ['one', 'apple', 3.14, True]
# Adding an item
my_list.append("new item")
print(my_list) # Output: ['one', 'apple', 3.14, True, 'new item']
Tuple (tuple)
A tuple is an ordered collection of items, enclosed in parentheses (). Tuples are immutable, so
once created, their content cannot be changed.
# Creating a tuple
my_tuple = (1, "apple", 3.14, True)
# Accessing items by index
print(my_tuple[1]) # Output: apple
# Trying to modify a tuple will cause an error
# my_tuple[0] = "one" # This would raise a TypeError
4. Dictionary (dict)
A dictionary is an unordered collection of key-value pairs, enclosed in curly braces {}. Each
item consists of a unique key and its corresponding value. Dictionaries are mutable.
# Creating a dictionary
person = {
"name": "Alice",
"age": 25,
"city": "New York"
}
# Accessing a value by its key
print(person["name"]) # Output: Alice
# Modifying a value
person["age"] = 26
print(person) # Output: {'name': 'Alice', 'age': 26, 'city': 'New
York'}
# Adding a new key-value pair
person["job"] = "Engineer"
print(person) # Output: {'name': 'Alice', 'age': 26, 'city': 'New
York', 'job': 'Engineer'}
5. Set (set)
A set is an unordered collection of unique items, enclosed in curly braces {}. Sets do not allow
duplicate elements. Sets are mutable, but the items they contain must be immutable.
# Creating a set (duplicates are automatically removed)
my_set = {1, 2, 3, "hello", 2, 3}
print(my_set) # Output: {1, 2, 3, 'hello'}
# Adding an item
my_set.add(4)
print(my_set) # Output: {1, 2, 3, 4, 'hello'}
# Removing an item
my_set.remove("hello")
print(my_set) # Output: {1, 2, 3, 4}
Identifiers and Reserved Words
● Identifiers: An identifier is a name given to a variable, function, class, or other object.
○ Must start with a letter (a-z, A-Z) or an underscore (_).
○ Can be followed by letters, numbers (0-9), or underscores.
○ Cannot be a reserved keyword.
○ Python is case-sensitive (age and Age
○ are different variables).
● Reserved Words (Keywords): These are words that have special meaning in Python
and cannot be used as identifiers.
False None True and as
assert async awai brea class
t k
continu def del elif else
e
except finall for from globa
y l
if import in is lambd
a
nonloca not or pass raise
l
return try whil with yield
e
Lines and Indentation
Unlike many other languages that use braces {} to define blocks of code, Python uses
indentation. A code block starts with an indentation and ends with the first unindented line. The
standard is to use four spaces per indentation level.
if True:
print("This is inside the if block.") # Indented
print("This is also inside.")
print("This is outside the if block.") # Not indented
Multi-line Statements
Statements in Python typically end with a new line. However, you can make a statement span
multiple lines by using:
1. Line Continuation Character (\):
total = 1 + 2 + 3 + \
4 + 5 + 6
print(total) # Output: 21
2.
Implicit Continuation (inside (), [], {}):
days = ['Monday', 'Tuesday', 'Wednesday',
'Thursday', 'Friday']
Comments
Comments are used to explain code. They are ignored by the interpreter.
● Single-line comments start with a hash (#).
# This is a single-line comment
name = "Alice" # This is an inline comment
●
Multi-line comments can be written using triple quotes (""" or '''). These are
technically multi-line strings, but they are often used for comments.
"""
This is a multi-line comment
or a docstring, which is used to
document functions and classes.
"""
Quotation
Strings can be enclosed in:
● Single quotes ('): 'Hello'
● Double quotes ("): "Hello"
● Triple quotes (""" or '''): For multi-line strings.
quote = """This is a
multi-line string."""
Input/Output
● Input: To get input from the user, use the input() function. It reads a line from the
input, converts it to a string, and returns it.
name = input("Enter your name: ")
age_str = input("Enter your age: ")
age = int(age_str) # input() always returns a string, so convert it to
an integer
print(f"Hello, {name}! You are {age} years old.")
●
Output: To display output, use the print() function.
print("Hello, World!")
Output Formatting
You can format strings to embed variables within them in a clean way.
● f-Strings (Formatted String Literals): This is the modern and most popular way. Prefix
the string with f and place variables inside curly braces {}.
name = "Alice"
age = 30
print(f"Her name is {name} and she is {age} years old.")
# Output: Her name is Alice and she is 30 years old.
●
String .format() method:
print("Her name is {} and she is {} years old.".format(name, age))
3. Variables
In Python, you don't need to declare a variable's type. A variable is created the moment you first
assign a value to it. This is called dynamic typing.
Simple Variable Assignment
name = "Alice" # String
age = 25 # Integer
height = 5.6 # Float
is_student = True # Boolean
Assigning Multiple Values
You can assign values to multiple variables in one line.
● Multiple variables, multiple values:
x, y, z = 10, 20, "hello"
print(x) # Output: 10
print(z) # Output: hello
●
One value to multiple variables:
a = b = c = 100
print(a, b, c) # Output: 100 100 100
Global and Local Variables
The scope of a variable is the region of the program where it is accessible.
● Local Variables: Variables declared inside a function are local to that function. They
can only be accessed from within that function.
def my_function():
message = "Hello from a function" # Local variable
print(message)
my_function()
# print(message) # This would cause an error
●
Global Variables: Variables declared outside of any function are global. They can be
accessed from anywhere in the code.
greeting = "Hello from global scope" # Global variable
def another_function():
print(greeting) # Accessing the global variable
another_function()
●
The global keyword: To modify a global variable from inside a function, you must use
the global keyword.
count = 0 # Global variable
def increment():
global count
count += 1
print(f"Count inside function: {count}")
increment()
print(f"Count outside function: {count}") # Output: 1
4. Python Decision Making
if, elif, else Statements
These statements allow you to execute code based on certain conditions.
● if-else:
age = 18
if age >= 18:
print("You are an adult.")
else:
print("You are a minor.")
●
if-elif-else (The "elif" ladder): Used to check multiple conditions.
score = 85
if score >= 90:
print("Grade: A")
elif score >= 80:
print("Grade: B")
elif score >= 70:
print("Grade: C")
else:
print("Grade: F")
●
Nested if: You can place if statements inside other if statements.
num = 15
if num >= 0:
if num == 0:
print("Zero")
else:
print("Positive number")
else:
print("Negative number")
match Statement
Introduced in Python 3.10, the match statement (structural pattern matching) is similar to a
switch statement in other languages. It compares a value against several patterns.
def http_status(status):
match status:
case 200:
return "OK"
case 404:
return "Not Found"
case 500:
return "Internal Server Error"
case _: # The underscore is a wildcard, matches anything
return "Unknown status"
print(http_status(404)) # Output: Not Found
print(http_status(201)) # Output: Unknown status
5. Loops
Loops are used to execute a block of code repeatedly.
while Loop
The while loop repeats as long as a condition is true.
count = 1
while count <= 5:
print(f"Count is: {count}")
count += 1
# Output:
# Count is: 1
# Count is: 2
# Count is: 3
# Count is: 4
# Count is: 5
for Loop
The for loop iterates over a sequence (like a list, tuple, string, or range).
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)
The range() Method
The range() function generates a sequence of numbers, which is often used with for loops.
● range(stop): Goes from 0 up to (but not including) stop.
● range(start, stop): Goes from start up to stop.
● range(start, stop, step): Goes from start up to stop, incrementing by step.
for i in range(5): # 0, 1, 2, 3, 4
print(i, end=" ")
print()
for i in range(2, 6): # 2, 3, 4, 5
print(i, end=" ")
print()
for i in range(0, 10, 2): # 0, 2, 4, 6, 8
print(i, end=" ")
print()
Nested Loops
You can use one or more loops inside another loop. This is useful for working with 2D data
structures or creating patterns.
# Example: Printing a 3x3 grid
for i in range(3): # Outer loop for rows
for j in range(3): # Inner loop for columns
print(f"({i},{j})", end=" ")
print() # Newline after each row
Loop Control Statements (break, continue, pass)
● break: Immediately terminates the loop.
for i in range(10):
if i == 5:
break # Stop the loop when i is 5
print(i) # Prints 0, 1, 2, 3, 4
●
continue: Skips the rest of the current iteration and proceeds to the next one.
for i in range(10):
if i % 2 == 0:
continue # Skip even numbers
print(i) # Prints 1, 3, 5, 7, 9
●
pass: Does nothing. It's used as a placeholder where syntax requires a statement, but
you don't want any code to execute.
def my_empty_function():
pass # To be implemented later
Pattern Design with Nested Loops
Nested loops are great for printing patterns.
# Example: Right-angled triangle
rows = 5
for i in range(1, rows + 1):
for j in range(i):
print("*", end="")
print()
# Output:
# *
# **
# ***
# ****
# *****
6. Functions
A function is a reusable block of code that performs a specific task.
Defining and Calling Functions
You define a function using the def keyword.
# Defining a function
def greet(name):
"""This function greets the person passed in as a parameter."""
print(f"Hello, {name}!")
# Calling the function
greet("Alice") # Output: Hello, Alice!
greet("Bob") # Output: Hello, Bob!
Types of Arguments
1. Required Arguments (Positional): Arguments passed to a function in the correct
positional order.
def add(a, b):
return a + b
result = add(5, 3) # a=5, b=3
2.
Keyword Arguments: You can identify arguments by their names. The order doesn't
matter.
def show_info(name, age):
print(f"Name: {name}, Age: {age}")
show_info(age=30, name="Alice")
3.
Default Arguments: A function can have arguments with default values.
def greet(name, message="Good morning!"):
print(f"{message}, {name}.")
greet("Alice") # Uses the default message
greet("Bob", "How are you?") # Overrides the default
4.
Variable-length Arguments:
○ *args (Non-Keyword Arguments): To pass a variable number of positional
arguments. They are collected into a tuple.
def sum_all(*numbers):
total = 0
for num in numbers:
total += num
return total
print(sum_all(1, 2, 3, 4)) # Output: 10
○
**kwargs (Keyword Arguments): To pass a variable number of keyword
arguments. They are collected into a dictionary.
def display_info(**person):
for key, value in person.items():
print(f"{key}: {value}")
display_info(name="Alice", age=30, city="New York")
Passing Arguments (Call by Object Reference)
Python's argument passing model is neither "call-by-value" nor "call-by-reference." It's "pass-by-
object-reference" or "pass-by-assignment."
● If you pass an immutable object (like a number, string, or tuple), the function cannot
change the original object's value.
def change_number(n):
n = 100 # A new object is created for n
num = 10
change_number(num)
print(num) # Output: 10 (original is unchanged)
●
If you pass a mutable object (like a list or dictionary), the function can modify the original
object.
def add_to_list(my_list):
my_list.append(4)
numbers = [1, 2, 3]
add_to_list(numbers)
print(numbers) # Output: [1, 2, 3, 4] (original is changed)
Recursive Functions
A function that calls itself is a recursive function. It's useful for tasks that can be broken down
into smaller, similar sub-problems.
# Example: Factorial
def factorial(n):
if n == 1:
return 1 # Base case
else:
return n * factorial(n - 1) # Recursive step
print(factorial(5)) # Output: 120
Lambda Expressions (Anonymous Functions)
A lambda function is a small, anonymous function defined with the lambda keyword. It can take
any number of arguments but can only have one expression.
Syntax: lambda arguments: expression
# A regular function
def double(x):
return x * 2
# The equivalent lambda function
double_lambda = lambda x: x * 2
print(double(5)) # Output: 10
print(double_lambda(5)) # Output: 10
Lambda functions are often used with functions like map(), filter(), and sorted().
7. Lists
A list is an ordered and mutable (changeable) collection of items. Lists are created using square
brackets [].
Introduction to Lists
# Creating lists
empty_list = []
fruits = ["apple", "banana", "cherry"]
numbers = [1, 2, 3, 4, 5]
mixed_list = [1, "hello", 3.14, True]
Operations on Lists
Method Description Example
append(item) Adds an item to the end of the list. fruits.append("orange"
)
insert(i, Inserts an item at a given index. fruits.insert(1,
item) "mango")
remove(item) Removes the first occurrence of an item. fruits.remove("banana"
)
pop(i) Removes and returns the item at index fruits.pop(0)
i.
sort() Sorts the list in place. numbers.sort()
reverse() Reverses the list in place. fruits.reverse()
len(list) Returns the number of items in the list. len(fruits)
Looping on Lists
You can easily iterate through the items in a list using a for loop.
for fruit in fruits:
print(fruit)
Indexing and Slicing
● Indexing: Accessing a single element using its position. Indexing starts at 0.
fruits = ["apple", "banana", "cherry"]
print(fruits[0]) # Output: apple
print(fruits[-1]) # Output: cherry (negative indexing from the end)
●
Slicing: Accessing a sub-section of the list. Syntax: list[start:stop:step]
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(numbers[2:5]) # Output: [2, 3, 4] (items from index 2 to 4)
print(numbers[:4]) # Output: [0, 1, 2, 3] (from the beginning to
index 3)
print(numbers[6:]) # Output: [6, 7, 8, 9] (from index 6 to the end)
print(numbers[::2]) # Output: [0, 2, 4, 6, 8] (every second item)
Passing Lists Through Functions
As mentioned earlier, lists are mutable. When you pass a list to a function, you are passing a
reference to the original list. Any modifications made inside the function will affect the original
list.
def modify_list(items):
items.pop(0) # Remove the first item
items.append("new_item")
my_items = [10, 20, 30]
print(f"Original list: {my_items}")
modify_list(my_items)
print(f"List after function call: {my_items}")
# Output:
# Original list: [10, 20, 30]
# List after function call: [20, 30, 'new_item']
8. Practice Questions
Basics & Variables
1. Write a program that takes the user's name and age as input and prints a message like
"Hello [Name], you will be [Age+1] next year."
2. What is the difference between a local and a global variable? Provide a code example.
3. Write a program to swap two numbers without using a temporary variable.
Decision Making & Loops
4. Write a program that checks if a number is positive, negative, or zero.
5. Create a program that prints all the even numbers from 1 to 100 using a for loop and
the range() function.
6. Write a program to print the multiplication table of a number entered by the user using a
while loop.
7. Using nested loops, print the following pattern:
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
Functions
8. Write a function that takes a number as an argument and returns True if it's a prime
number and False otherwise.
9. Write a function that accepts a variable number of integer arguments (*args) and
returns their sum.
10. What is a lambda function? Write a lambda function that takes two numbers and returns
their product.
11. Explain Python's argument passing mechanism. What happens when you pass a list to a
function versus when you pass a string?
Lists
12. Given a list numbers = [10, 50, 20, 40, 30], write code to sort it in descending
order.
13. Write a program to find the largest and smallest numbers in a list without using the built-
in max() and min() functions.
14. Write a function that takes a list as input and returns a new list containing only the
unique elements from the original list.