0% found this document useful (0 votes)
4 views38 pages

Python - Programming - Ipynb - Colab

The document provides an overview of Python programming, highlighting its high-level, interpreted nature, and applications in various fields. It covers basic syntax, data types, variables, and arithmetic operations, emphasizing readability, productivity, and ease of use. Additionally, it explains concepts like variable scope, type conversion, and various arithmetic operations including addition, subtraction, multiplication, and division.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views38 pages

Python - Programming - Ipynb - Colab

The document provides an overview of Python programming, highlighting its high-level, interpreted nature, and applications in various fields. It covers basic syntax, data types, variables, and arithmetic operations, emphasizing readability, productivity, and ease of use. Additionally, it explains concepts like variable scope, type conversion, and various arithmetic operations including addition, subtraction, multiplication, and division.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

9/9/25, 8:14 PM Python_Programming.

ipynb - Colab

Python is a high-level, interpreted programming language known for its readability and simplicity. It’s used in web development, data
analysis, artificial intelligence, scientific computing, and more.

Abstracted from Machine Code: High-level languages are far removed from the binary machine code that the computer's processor
understands. They use natural language elements and abstract away the hardware details.

Readable and Writable: They are designed to be readable and writable by humans. This means they use syntax and keywords that are
intuitive and closer to human languages.

Productivity: High-level languages enable programmers to write programs more quickly and with fewer errors, making them more
productive. Examples include Python, Java, and C++.

Interpreted Language

Execution by Interpreter: Interpreted languages are executed line-by-line by an interpreter at runtime, rather than being compiled into
machine code before execution. The interpreter translates each high-level instruction into machine code on the fly.

Platform Independence: Because the interpreter translates the code at runtime, the same high-level code can be run on different types of
hardware and operating systems without modification, as long as the appropriate interpreter is available.

Ease of Use and Flexibility: Interpreted languages often allow more flexibility with features like dynamic typing and dynamic execution of
code. This can make them easier to use for rapid development and prototyping.

Basic Syntax in Python

# 1. Indentation

if 5 > 2:
print("Five is greater than two.") # This line is indented, so it's inside the if block

Five is greater than two.

"""if 5 > 2:
print("Five is greater than two.")"""

'if 5 > 2:\nprint("Five is greater than two.")'

# 2. Comments

# This is a single-line comment

print("Hello, World!") # This comment is at the end of a line of code

Hello, World!

"""
This is a multi-line comment or docstring.
It can span multiple lines.
"""
print("Hello, World!")

Hello, World!

# 3. Readability

my_variable = 10
def my_function():
pass

dog = 'doberman'

car = 'German Shepherd'

# This is an example of a long comment that might need to be wrapped and fit within the 79 character limit

[Link] 1/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
# 4. Spacing
# Whitespace in Expressions and Statements
# Avoid extraneous whitespace.

# Correct:
x = 1
y = x + 2
print(y)

# Wrong:
x=1
y = x+2
print(y)

3
3

Data Types in Python

1. Integers - Whole numbers


2. Floats - Decimal point numbers
3. Booleans - True or False
4. Strings - Any data types, including text data, found within quotation marks " "

# Integers

x = 5
y = -3
z = 0
print(type(x))
print(type(y))
print(type(z))

<class 'int'>
<class 'int'>
<class 'int'>

# 2. Floats

a = 3.14
b = -2.5
c = 0.0
print(type(a))
print(type(b))
print(type(c))

<class 'float'>
<class 'float'>
<class 'float'>

# 3. Strings

greeting = "Hello, World!"


name = 'Alice'
multi_line = """This is a
multi-line string."""
print(type(greeting))
print(type(name))

<class 'str'>
<class 'str'>

# Booleans

is_sunny = True
is_raining = False
print(type(is_sunny))
print(type(is_raining))

<class 'bool'>
<class 'bool'>

Variables

[Link] 2/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
1. Store Data: You can store values or results of computations in variables for later use.
2. Manipulate Data: You can perform operations or calculations using variables.
3. Reuse Data: Variables allow you to reuse the same value in multiple places within your code without having to repeat it.

print(dog)

doberman

# Creating variables and assigning values to them

# You create a variable by naming something, once you name it, you assign it a value,
# you assign the value after the equals (=) sign
# after the equals sign, you give your value

x = 5
y = "Hello, World!"
is_sunny = True

# Using variables in expressions

z = x * 2
greeting = y + " Welcome!"
print(z)
print(greeting)

10
Hello, World! Welcome!

# Modifying variables

x = x + 1
print(x)

x = 5
x_1 = "Hello"
print(x)

z = x + z
print(z)

15

Variable Names

1. Descriptive Names - Choose meaningful and descriptive names for variables to make your code easier to understand.

num_students = 20

2. Snake Case - Use snake_case (lowercase words separated by underscores) for variable names in Python.

total_amount = 100

3. Avoid Reserved Keywords - Avoid using Python reserved keywords (e.g., if, for, while) as variable names.

4. Dynamic Typing - Python is dynamically typed, meaning you don't need to declare the type of a variable explicitly. Python infers the
type based on the value assigned to it.

x = 5 # x is an integer x = "Hello" # x is now a string

5. Constants - Although Python doesn't have built-in constants, programmers often use variables in all capital letters to represent
constants.

PI = 3.14

MAX_VALUE = 100

Variable Scope

1. Global Scope: Variables defined outside of any function or class are in the global scope and can be accessed from anywhere in the
code.

[Link] 3/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
2. Local Scope: Variables defined inside a function or a class method are in the local scope and can only be accessed within that
function or method.

# Global Scope

x = 10 # Global variable

def my_function():
print(x) # Accessing global variable from inside function

my_function()

10

def my_function_1():
y = 20 # Local variable
print(y)

my_function_1()

# print(y) # This will raise a NameError since y is not defined outside the function

20

Enclosing Scope (Nested Functions): Variables defined in an enclosing function are accessible within nested functions, but not outside
the enclosing function.

def outer_function():
z = 30

def inner_function():
print(z)

inner_function()

outer_function()

30

Variable Types and Type Conversion

var_1 = 10
print(type(var_1))

<class 'int'>

Type conversion functions (int(), float(), str(), etc.) allow you to convert data from one type to another when needed.

# Convert var_1 to a string

var_1 = str(var_1)
print(type(var_1))

<class 'str'>

sum = '10' + '5' + '3'


print(sum)
print(type(sum))

1053
<class 'str'>

a = '10'
b = '5'
c = '3'

print(type(a))
print(type(b))
print(type(c))

a_1 = int(a)

[Link] 4/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
b_1 = int(b)
c_1 = int(c)

print(type(a_1))
print(type(b_1))
print(type(c_1))

<class 'str'>
<class 'str'>
<class 'str'>
<class 'int'>
<class 'int'>
<class 'int'>

sum = a_1 + b_1 + c_1


print(sum)

18

Arithmetic Operations

# Addition
result_addition = 5 + 3
print(result_addition)

# Addition of floats
result = 3.5 + 2.5
print(result)

6.0

# Mixed addition
result_1 = 4 + 2.5
print(result_1)

6.5

# Addition of variables
x = 10
y = 20
result_2 = x + y
print(result_2)

30

"""# Concatenation of strings


greeting = "Hello"
name = "Alice"
message = greeting + ", " + name
print(message)"""

'# Concatenation of strings\ngreeting = "Hello"\nname = "Alice"\nmessage = greeting + ", " + name\nprint(message)'

"""# Adding lists


list1 = [1, 2, 3]
list2 = [4, 5, 6]
result_3 = list1 + list2
print(result_3)"""

'# Adding lists\nlist1 = [1, 2, 3]\nlist2 = [4, 5, 6]\nresult_3 = list1 + list2\nprint(result_3)'

# Subtraction
result_subtraction = 5 - 3
print(result_subtraction)

# Addition
result_addition = 5 - 3
print(result_addition)

[Link] 5/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
# Subtraction of variables
x = 20
y = 10
result_4 = x - y
print(result_4)

10

"""# Removing elements from lists using the subtraction sigh, this will not work and will give you a 'TypeError'
numbers = [1, 2, 3, 4, 5]
numbers_removed = numbers - [3, 4]
print(numbers_removed)"""

'# Removing elements from lists using the subtraction sigh, this will not work and will give you a 'TypeError'\nnumbers = [1,
2, 3, 4, 5]\nnumbers_removed = numbers - [3, 4]\nprint(numbers_removed)'

# Multiplication (*)
result_multiplication = 4 * 6
print(result_multiplication)

24

# Multiplication
result_multiplication1 = -4 * 6
print(result_multiplication1)

-24

# Multiplication of variables
x = 10
y = 3
result_5 = x * y
print(result_5)

30

# Repeating strings - occurs when you multiply strings


message = "Hello, " * 3
print(message)

Hello, Hello, Hello,

# Concatenating lists
numbers = [1, 2, 3]
numbers_multiplied = numbers * 2
print(numbers_multiplied)

[1, 2, 3, 1, 2, 3]

# Division of integers
result_6 = 10 / 3
print(result_6)

3.3333333333333335

# Division of variables
x = 20
y = 4
result_7 = x / y
print(result_7)

5.0

"""# Division by zero - python does not support division by '0'


result_8 = 10 / 0
print(result_8)"""

'# Division by zero - python does not support division by '0'\nresult_8 = 10 / 0\nprint(result_8)'

Floor Division (//)

The floor division operator // is used to perform division and return the integer part of the result (rounded down).

Your output is rounded 'down' to the nearest whole number.

[Link] 6/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
# Division of integers
result_9 = 10 // 3
print(result_9)

result_10 = 20 / 3
print(result_10)

6.666666666666667

result_11 = 20 // 3
print(result_11)

# Floor division of variables


x = 20
y = 4
result_12 = x // y
print(result_12)

# Floor division with negative numbers


result_13 = -7 // 2
print(result_13)

-4

Modulus (Remainder) (%)

The modulus operator % returns the remainder of the division operation.

# Modulus (Remainder)
result_modulus = 10 % 3
print(result_modulus)

# Modulus of floats
result_14 = 7.5 % 2.5
print(result_14)

0.0

# Modulus with negative numbers - Homework


result_15 = -7 % 3
print(result_15)

The modulus operation in Python returns a result that has the same sign as the divisor (in this case, 3, which is positive).

The mathematical result of -7 / 3 gives a quotient of -2 with a remainder of -1


keyboard_arrow_down because − 7
( − 2 ) × 3 + − 1 −7=(−2)×3+−1.

However, since Python's modulus retains the divisor’s sign, it "wraps around" by adjusting the remainder to be non-negative. Instead of
returning -1, it returns 2 because 3 - 1 = 2.

-1 0 1 2 3 - refer to your number line knowledge

# Modulus for even/odd checking


number = 10
is_even = number % 2 == 0
print(is_even)

True

Exponentiation (**)

[Link] 7/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
The exponentiation operator ** is used to raise one operand to the power of another.

# Exponentiation
result_exponentiation = 2 ** 3
print(result_exponentiation)

Combined Arithmetic Operations

# Combined Arithmetic Operations


result_combined = (5 * 2) + (10 // 3) - (2 ** 2)
# 10 + 3 - 4
# 13 - 4
# 9
print(result_combined)

Combined arithmetic operations in Python follow the BODMAS (Brackets, Orders, Division and Multiplication, Addition and Subtraction)
rules, also known as the PEMDAS (Parentheses, Exponents, Multiplication and Division, Addition and Subtraction) rules.

# Expression with BODMAS/PEMDAS rules


result_bodmas = 4 + 5 * 2 - 3
print("Result with BODMAS/PEMDAS rules:", result_bodmas)

Result with BODMAS/PEMDAS rules: 11

# Expression without BODMAS/PEMDAS rules


result_no_bodmas = (4 + 5) * 2 - 3
print("Result without BODMAS/PEMDAS rules:", result_no_bodmas)

Result without BODMAS/PEMDAS rules: 15

Comparison Operations

Comparison operations in Python are used to compare values and determine the relationship between them.

These operations return a Boolean value (True or False) based on whether the comparison is true or false.

Python supports several comparison operators, which are commonly used to compare numbers, strings, and other data types.

# 1. Equal to (==) - The equal to operator == checks if two operands are equal.

# Equal to
result_16 = 5 == 5
print(result_16)

result_17 = 5 == 6
print(result_17)

True
False

x = 5
y = 5
result_18 = x == y # This will evaluate to True because x and y are equal.
print(result_18)

True

result_19 = "hello" == "world"


print(result_19)

False

name1 = "Alice"
name2 = "Alice"
result_20 = name1 == name2
print(result_20)

[Link] 8/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab

True

result_21 = (2 + 3) == (4 + 1)
print(result_21)

True

# 2. Not equal to (!=) - The not equal to operator != checks if two operands are not equal.

result_22 = 5 != 3
print(result_22)

True

result_23 = 3 != 3
print(result_23)

False

x = 5
y = 10

result_24 = x != y # This will evaluate to True because x and y are not equal.
print(result_24)

True

result_25 = "hello" != "world"


print(result_25)

True

result_26 = (2 + 3) != (4 + 1)
print(result_26)

False

# 3. Greater than (>) - The greater than operator > checks if the left operand is greater than the right operand.

result_27 = 5 > 3
print(result_27)

True

result_28 = 2 > 3
print(result_28)

False

result_29 = "banana" > "apple"


print(result_29)

'''In Python, strings are compared lexicographically (based on the Unicode values of their characters).
In this example, "banana" is greater than "apple" because the Unicode value of 'b' is greater than 'a'.
'''

True
'In Python, strings are compared lexicographically (based on the Unicode values of their characters).\nIn this example, "banan
a" is greater than "apple" because the Unicode value of \'b\' is greater than \'a\'.\n'

age1 = 30
age2 = 25
result_30 = age1 > age2
print(result_30)

True

result_31 = (3 + 4) > (2 * 3)
print(result_31)

[Link] 9/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab

True

# 4. Less than (<) - The less than operator < checks if the left operand is less than the right operand.

'''Assignment - try out the same codes we used for greater than but convert the symbol to less than instead'''

'Assignment - try out the same codes we used for greater than but convert the symbol to less than instead'

# 5. Greater than or equal to (>=) - The greater than or equal to operator >= checks if the left operand is greater than or eq

result_32 = 5 >= 5
print(result_32)

True

# 6. Less than or equal to (<=) - The less than or equal to operator <= checks if the left operand is less than or equal to th

result_33 = 5 <= 2
print(result_33)

False

Chaining Comparison Operators

Chaining comparison operators in Python allows you to compare multiple values in a single expression, making the code more concise and
readable. When you chain comparison operators, Python evaluates the expression from left to right and returns True only if all
comparisons in the chain are True.

# a < b < c
# a < b and b < c

x = 5
y = 10
z = 15
result_33 = x < y < z
print(result_33)

True

x = 5
y = 10
z = 2
result_34 = x < y < z
print(result_34)

False

Start coding or generate with AI.

Logical Operations

Logical operators are used to combine multiple conditions and return a boolean result.

keyboard_arrow_down AND
result_and = (5 > 3) and (7 < 10) # Output: True

OR
result_or = (4 == 4) or (6 != 6) # Output: True

NOT
result_not = not (3 > 5) # Output: True

[Link] 10/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
Logical operators in Python are used to combine conditional statements. These operators allow you to evaluate multiple conditions and
return a Boolean value (True or False) based on the logical relationships between them. The primary logical operators in Python are and,
or, and not.

and Operator

The and operator returns True if both operands are True. If either operand is False, it returns False. Syntax: condition1 and condition2

a = 5
b = 10
c = 15

result_35 = (a < b) and (b < c) # Both conditions are True, so result is True.
print(result_35)

True

a = 5
b = 10
c = 15

result_36 = (a < b) and (b > c) # Both conditions are not True, so result is True.
print(result_36)

False

is_raining = True
is_sunny = False
result_37 = is_raining and is_sunny # Both conditions need to be True.
print(result_37)

False

or Operator

The or operator returns True if at least one of the operands is True. If both operands are False, it returns False. Syntax: condition1 or
condition2

a = 5
b = 10
c = 15

result_38 = (a < b) or (b > c) # The first condition is True, so result is True.


print(result_38)

True

a = 5
b = 10
c = 15

result_39 = (a > b) or (b > c) # Both conditions are false


print(result_39)

False

a = 5
b = 10
c = 15

result_40 = (a > b) or (b < c) or (a < c) # The second and third conditions are True.
print(result_40)

True

is_raining = True
is_sunny = False

result_41 = is_raining or is_sunny # At least one condition is True.


print(result_41)

[Link] 11/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab

True

not Operator

The not operator is a unary operator that returns True if the operand is False, and False if the operand is True. Syntax: not condition

The not operator in Python is a logical operator used to invert the value of a boolean expression. It returns True if the operand is False, and
False if the operand is True. This operator is useful for reversing the meaning of a condition, making it the simplest form of logical
negation.

a = 5
b = 10

result_42 = not (a > b) # The condition a > b is False, so result is True.


print(result_42)

True

result_43 = not (a < b) # The condition a < b is True, so result is False.


print(result_43)

False

is_raining = True

result_44 = not is_raining # The variable is_raining is True, so not True is False.
print(result_44)

False

Order of Operations for Logical Operators

Python evaluates logical operators in the following order of precedence: not first, and second, or last. You can use parentheses to control
the order of evaluation explicitly.

a = 5
b = 10
c = 15

result_44 = not a < b and b < c # not (True) and True => False and True => False
# a < b = True; this would then mean that not True = False
# result_44 = False and b < c
# is b less than c = True
# result_44 = False and True
# when you are using the 'and' operator, you get back a 'True' output when all the consditions are 'True'
# In this instance, one of the conditions is False
# Which means, my overall output would then be False
print(result_44)

False

result_45 = not (a < b and b < c) # not (True and True) => not True => False
print(result_45)

False

Start coding or generate with AI.

Assignment Operations

Assignment operators are used to assign values to variables.

x = 5 # Assigning value 5 to variable x

y = 10
y += 3 # Equivalent to: y = y + 3 (adds 3 to the current value of y)

Compound Assignment Operators

[Link] 12/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
Compound assignment operators combine a standard arithmetic or bitwise operation with assignment. They simplify the syntax and make
the code more concise.

Start coding or generate with AI.

+= (Add and Assign)

Adds the right operand to the left operand and assigns the result to the left operand.

a = 5
a += 3 # Equivalent to a = a + 3
print(a)

Start coding or generate with AI.

-= (Subtract and Assign)

Subtracts the right operand from the left operand and assigns the result to the left operand.

a = 5
a -= 2 # Equivalent to a = a - 2
print(a)

Start coding or generate with AI.

*= (Multiply and Assign)

Multiplies the left operand by the right operand and assigns the result to the left operand.

a = 5
a *= 4 # Equivalent to a = a * 4
print(a)

20

Start coding or generate with AI.

/= (Divide and Assign)

Divides the left operand by the right operand and assigns the result to the left operand.

a = 10
a /= 2 # Equivalent to a = a / 2
print(a)

5.0

Start coding or generate with AI.

//= (Floor Divide and Assign)

Performs floor division on the left operand by the right operand and assigns the result to the left operand.

a = 10
a //= 3 # Equivalent to a = a // 3
print(a)

Start coding or generate with AI.

%= (Modulus and Assign)

[Link] 13/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
Takes the modulus using the left and right operands and assigns the result to the left operand.

a = 10
a %= 3 # Equivalent to a = a % 3
print(a)

Start coding or generate with AI.

**= (Exponentiate and Assign)

Raises the left operand to the power of the right operand and assigns the result to the left operand.

a = 2
a **= 3 # Equivalent to a = a ** 3
print(a)

Start coding or generate with AI.

Membership Operations

Membership operators are used to test if a value is present in a sequence (e.g., list, tuple, string).

in Operator: Tests if a value exists in a sequence. Returns True if the value is found, otherwise returns False.
not in Operator: Tests if a value does not exist in a sequence. Returns True if the value is not found, otherwise returns False.

# 1. Using in Operator

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


print("apple" in fruits) # Output: True
print("orange" in fruits)

True
False

text = "hello world"


print("hello" in text) # Output: True
print("world" in text) # Output: True
print("Python" in text) # Output: False

True
True
False

# 2. not in Operator

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


print("apple" not in fruits)
print("orange" not in fruits)

False
True

Identity Operations

Identity operators are used to compare the memory locations of two objects.

These operators are essential for checking whether two variables point to the same object in memory. Python provides two identity
operators: is and is not.

x = [1, 2, 3]
y = [1, 2, 3]

# IS Operator
result_is = x is y
print(result_is)

False

[Link] 14/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab

# IS NOT
result_is_not = x is not y
print(result_is_not)

True

is Operator: Tests if two variables refer to the same object. Returns True if both variables point to the same object, otherwise returns
False.

is not Operator: Tests if two variables do not refer to the same object. Returns True if both variables point to different objects, otherwise
returns False.

Introduction to Lists, Tuples, and Dictionaries

Start coding or generate with AI.

1. Lists

A list is an ordered, mutable collection of items. Lists can contain elements of different data types, including other lists.

Lists are one of the most versatile and commonly used data structures in Python. They allow you to store collections of items in a single
variable. Lists are ordered, mutable, and can contain elements of different data types, including other lists.

Creating a List A list is created by placing all the items (elements) inside square brackets [], separated by commas.

# Empty list
my_list = []

# List of integers
my_list = [1, 2, 3, 4, 5]

# List of mixed data types


my_list = [1, "apple", 3.14, True]

# List of lists
nested_list = [[1, 2, 3], ["a", "b", "c"]]

# List of integers
my_list = [1, 2, 3, 4, 5]

# python uses zero-based indexing - you start counting from zero (0)
# The number 1 in my_list occupies the position denoted by index 0, etc.

"""Ordered:
The elements in a list have a defined order. When you add items to a list, they are stored in a specific sequence. This order
"""

'Ordered:\nThe elements in a list have a defined order. When you add items to a list, they are stored in a specific sequence.
This order is maintained, which means the elements can be accessed and manipulated based on their position (index).\n'

"""Mutable:
Lists are mutable, meaning you can change their content after they are created. This includes adding, removing, and modifying
"""

'Mutable:\nLists are mutable, meaning you can change their content after they are created. This includes adding, removing, and
modifying elements \n'

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


fruits[1] = "blueberry" # you're accessing the item at index 1 i.e. banana and replacing it with a blueberry instead
print(fruits)

['apple', 'blueberry', 'cherry']

"""Dynamic: Lists can grow and shrink in size as needed. You can add or remove elements dynamically.
"""

'Dynamic: Lists can grow and shrink in size as needed. You can add or remove elements dynamically.\n'

fruits = ["apple", "banana"]


[Link]("cherry") # adds values at the far righ end of a list using .append()

[Link] 15/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
print(fruits)

['apple', 'banana', 'cherry']

[Link]("banana")
print(fruits)

['apple', 'cherry']

# the code above removes a given item from your list by indicating the exact name of the item

"""Indexing and Slicing:


Lists support indexing and slicing, allowing you to access and manipulate subparts of the list. Indexing starts from 0 for the
"""

'Indexing and Slicing:\nLists support indexing and slicing, allowing you to access and manipulate subparts of the list. Indexi
ng starts from 0 for the first element.\n'

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


print(fruits[1:4])
# when slicing, include your start index and stop/end index
# what shows that you're slicing is the colon symbol ':'
# when you slice, your output includes the item at your start index but it excludes the item at your stop index

['banana', 'cherry', 'date']

print(fruits[2])

cherry

Accessing Elements in Lists in Python

Accessing elements in lists is a fundamental operation that allows you to retrieve and manipulate data stored within the list.

Python provides several ways to access elements, including indexing, slicing, and using negative indices.

# 1. Basic Indexing: Elements in a list can be accessed by their index. Python uses zero-based indexing, which means the first

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

# Accessing the first element


print(fruits[0])
# Accessing the second one
print(fruits[1])
# Accessing the third element
print(fruits[2])

apple
banana
cherry

# Negative Indexing: Negative indexing allows you to access elements from the end of the list. The last element is at index -1

# Accessing the last element


fruits = ["apple", "banana", "cherry", "date"]
print(fruits[-1])

date

# Accessing the second last element


print(fruits[-2])

cherry

Slicing

Slicing allows you to access a range of elements.

[Link] 16/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
The syntax for slicing is list[start:end], where start is the index of the first element to include, and end is the index of the first element to
exclude.

# Basic Slicing

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

# Accessing elements from index 1 to 3 (excluding index 3)


print(fruits[1:3])

['banana', 'cherry']

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


# Accessing the first three elements
print(fruits[:3])
# when you don't specify the index value to the left side of the colon, you're telling python to automatically pick your start

['apple', 'banana', 'cherry']

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

# Accessing elements from index 2 to the end


print(fruits[2:])
# when you don't specify your stop/end index, you're telling to give you all the elements from your start index all the way to

['cherry', 'date', 'elderberry']

List Methods

# .insert(): Inserts an element at a specified position.

fruits = ["apple", "banana"]


[Link](1, "cherry")
print(fruits)

['apple', 'cherry', 'banana']

# extend(): Extends the list by appending elements from another list or any iterable.

fruits = ["apple", "banana"]


[Link](["cherry", "date"])
print(fruits)

['apple', 'banana', 'cherry', 'date']

# remove(): Removes the first occurrence of a specified value.

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


[Link]("banana")
print(fruits)

['apple', 'cherry']

# pop(): Removes and returns the element at a specified position (default is the last element).

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


fruit = [Link]()
print(fruit)

cherry

# clear(): Removes all elements from the list.

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


[Link]()
print(fruits)

[]

[Link] 17/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
# sort(): Sorts the elements of the list in place (ascending order by default).

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


[Link]()
print(fruits)

['apple', 'banana', 'cherry']

# You can also sort in descending order by passing the reverse=True argument.

[Link](reverse=True)
print(fruits)

['cherry', 'banana', 'apple']

# reverse(): Reverses the elements of the list in place.

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


[Link]()
print(fruits)

['cherry', 'banana', 'apple']

# index(): Returns the index of the first occurrence of a specified value.

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


index = [Link]("banana")
print(index)

# count(): Returns the number of occurrences of a specified value/element.

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


count = [Link]("banana")
print(count)

# copy(): Returns a shallow copy of the list.

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


fruits_copy = [Link]()
print(fruits_copy)

['apple', 'banana', 'cherry']

# list() constructor: You can create a new list by passing an iterable to the list() constructor.

fruits = ("apple", "banana", "cherry") # this is a tuple

fruits = list(("apple", "banana", "cherry"))


print(fruits)

['apple', 'banana', 'cherry']

# len(): Although not a method of the list object, len() is a built-in function that returns the number of elements in a list

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


print(len(fruits))

# where to get the comprehensive number of methods you can apply to 'lists' in python

# You'll find it in Python documentation - [Link]

Start coding or generate with AI.

[Link] 18/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab

Tuples

A tuple is an ordered, immutable collection of items. Like lists, tuples can contain elements of different data types.

Tuples are one of the fundamental data structures in Python. They are similar to lists but have some distinct characteristics: their creation,
characteristics, and common operations.

# Creating Tuples

# 1. Creating an Empty Tuple - You can create an empty tuple using parentheses () or the tuple() function.

# Using parentheses
empty_tuple = ()
print(empty_tuple)

()

# Creating an Empty Tuple Using the tuple() function

# The syntax for writing a function is this:


# You give your function a name; after the name, you add empty brackets/parentheses

empty_tuple = tuple()
print(empty_tuple)

()

# 2. Creating a Tuple with Elements

# Creating a tuple with multiple elements


my_tuple = (1, 2, 3)
print(my_tuple)

(1, 2, 3)

# 3. Creating a Tuple with One Element - To create a tuple with a single element, you must include a trailing comma. Without t

# With the comma, this is a tuple


single_element_tuple = (5,)
print(type(single_element_tuple))

<class 'tuple'>

# Without the comma, this is not a tuple


not_a_tuple = (5)
print(type(not_a_tuple))

<class 'int'>

# 4. Creating a Tuple from an Iterable - You can create a tuple from any iterable (e.g., list, string, range) using the tuple

# Creating a tuple from a list


my_list = [1, 2, 3]
my_tuple = tuple(my_list)
print(my_tuple)

(1, 2, 3)

# Creating a tuple from a string


my_string = "hello"
my_tuple = tuple(my_string)
print(my_tuple)

('h', 'e', 'l', 'l', 'o')

# Creating a tuple from a range


my_range = range(5) # range function gives you element valus starting from zero but stops just before your stop index
my_tuple = tuple(my_range)

[Link] 19/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
print(my_tuple)

(0, 1, 2, 3, 4)

# 5. Creating Nested Tuples - Tuples can contain other tuples as elements, allowing you to create nested structures.

nested_tuple = (1, (2, 3), (4, 5, 6))


print(nested_tuple)

(1, (2, 3), (4, 5, 6))

Start coding or generate with AI.

Key Features/Characteristics of Tuples

# 1. Ordered Collection - Tuples maintain the order of elements. This means that the order in which you insert elements into a

tuple_1 = (1, 2, 3, 4, 5)
print(tuple_1[0])
print(tuple_1[3])

1
4

'''# 2. Immutable - Once a tuple is created, its contents cannot be altered. This immutability makes tuples a reliable way to

tuple_2 = (1, 2, 3)
tuple_2[1] = 15'''

'# 2. Immutable - Once a tuple is created, its contents cannot be altered. This immutability makes tuples a reliable way to st
ore data that should not change throughout the program.\n\ntuple_2 = (1, 2, 3)\ntuple_2[1] = 15'

# 3. Heterogeneous - Tuples can contain elements of different data types, including integers, strings, lists, and even other t

tuple_3 = (1, "Hello", 3.14, [1, 2, 3], (4, 5))


print(tuple_3)

(1, 'Hello', 3.14, [1, 2, 3], (4, 5))

# 4. Indexed - Tuples use zero-based indexing, allowing you to access elements directly by their index positions.

tuple_4 = ('a', 'b', 'c', 'd')


print(tuple_4[1])
print(tuple_4[2])

b
c

# 5. Hashable - Since tuples are immutable, they can be used as keys in dictionaries if all elements within the tuple are also

dictionary_1 = {(1, 2): "a pair of numbers", (3, 4): "another pair"}
print(dictionary_1[(1, 2)])

a pair of numbers

# 6. Built-in Methods - Tuples have a limited set of built-in methods, reflecting their immutability. The most common methods

tuple_5 = (1, 2, 3, 2, 2)
print(tuple_5.count(2))

# index(): Returns the index of the first occurrence of a specified value/element.

tuple_6 = (1, 2, 3, 4)
print(tuple_6.index(3))

Accessing Tuple Elements

[Link] 20/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab

# 1. Accessing Individual Elements - Accessing individual elements of a tuple in Python is straightforward and involves using

my_tuple = ('a', 'b', 'c', 'd')


# Accessing elements by index
print(my_tuple[0])

# 2. Negative Indexing - Negative indexing in Python allows you to access elements of a tuple starting from the end, rather th

print(my_tuple[-1])

# 3. Accessing Nested Tuples

# Accessing elements within nested tuples


nested_tuple = ((1, 2), ('a', 'b', 'c'), (3, 4, 5))
print(nested_tuple[1])

('a', 'b', 'c')

# Accessing elements within nested tuples


nested_tuple = ((1, 2), ('a', 'b', 'c'), (3, 4, 5))
print(nested_tuple[1][0])
print(nested_tuple[2][0])

a
3

# Unpacking a tuple - It allows you to work with the individual elements of a tuple without needing to index into it repeatedl

my_tuple_1 = (a, b, c)
a, b, c = my_tuple_1
print(a, b, c)

8 10 15

my_tuple_2 = (a, c, b)
p, q, r = my_tuple_2
print(p, q, r)

8 15 10

# Length - len() function - You can determine the number of elements in a tuple

# Syntax - len(tuple_name)

tuple1 = (1, 2, 3, 4)
# Finding the length of a tuple
len(tuple1)

# max() Function - The max() function takes a tuple as its argument and returns the maximum value present in the tuple.

tuple1 = (5, 1, 8, 3)
# Finding max value
print(max(tuple1))

tuple2 = ('a', 'b', 'c', 'd')


print(max(tuple2))

tuple3 = ('air', 'accurate', 'apple', 'addition')


print(max(tuple3))

apple

[Link] 21/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
# min() Function - The min() function takes a tuple as its argument and returns the minimum value present in the tuple.

tuple4 = (5, 1, 8, 3)
# Finding min value
print(min(tuple4))

'''# sum() - Description: Returns the sum of all elements in a tuple. - Syntax: sum(tuple_name)

tuple5 = (1, 2, 3)
print(sum(tuple5))
'''

'# sum() - Description: Returns the sum of all elements in a tuple. - Syntax: sum(tuple_name)\n\ntuple5 = (1, 2, 3)\nprint(sum
(tuple5))\n'

'''tuple6 = (2,3,4)
print(sum(tuple6))'''

'tuple6 = (2,3,4)\nprint(sum(tuple6))'

# sorted() - Description: Returns a sorted list of the tuple's elements. Syntax: sorted(tuple)

t = (3, 1, 2)
print(sorted(t))
print(tuple(sorted(t))) # the tuple function here converts the list output into a tuple

[1, 2, 3]
(1, 2, 3)

# all() - Description: Returns True if all elements in the tuple are true. - Syntax: all(tuple)

t = (1, 2, 3)
print(all(t))

True

t2 = (0, 1, 2)
print(all(t2))

False

t = (-1, -2, -3)


print(all(t))

True

# any() - Description: Returns True if any element in the tuple is true. - Syntax: any(tuple)

t1 = (1, 2, 3)
print(any(t1))

t2 = (-1, -2, -3)


print(any(t2))

t3 = (0, 1, 2)
print(any(t3))

t4 = (0, 0, 2)
print(any(t4))

t5 = (0, 0, 0)
print(any(t5))

True
True
True
True
False

Start coding or generate with AI.

[Link] 22/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab

Converting a List to a Tuple

To convert a list to a tuple, you can use the tuple() function. This is useful when you want to make a sequence immutable to prevent
accidental modifications.

my_list = [1, 2, 3, 4]
my_tuple = tuple(my_list)
print(my_tuple)

(1, 2, 3, 4)

Converting a Tuple to a List

To convert a tuple to a list, you can use the list() function. This is useful when you need to modify the contents of a sequence that was
initially a tuple.

my_tuple = (1, 2, 3, 4)
my_list = list(my_tuple)
print(my_list)

[1, 2, 3, 4]

# Nested structure
nested_tuple = ([1, 2, 3], [4, 5, 6])

# Converting each nested list to a tuple


nested_converted = tuple(tuple(sublist) for sublist in nested_tuple)
print(nested_converted)

((1, 2, 3), (4, 5, 6))

Start coding or generate with AI.

Dictionaries

A dictionary is an unordered, mutable collection of key-value pairs. Each key must be unique and immutable, while values can be of any
data type.

Dictionaries are a powerful data structure in Python that allow you to store and manage data using key-value pairs. They are mutable,
unordered, and indexed by keys, which can be of any immutable type.

# Using curly braces


my_dict = {'name': 'Alice', 'age': 25, 'city': 'New York'}

Key Features

1.** Key-Value Pairs** - Each element in a dictionary is a pair consisting of a key and a value.

my_dict = {'name': 'Alice', 'age': 25, 'city': 'New York'}

2. Unordered - Dictionaries do not maintain the order of elements as inserted.

3. Mutable - You can change the contents of a dictionary after it is created.

4. Indexed by Keys - Access to dictionary elements is done using keys.

# Using the dict() constructor

my_dict = dict(name='Alice', age=25, city='New York')


print(my_dict)

{'name': 'Alice', 'age': 25, 'city': 'New York'}

Accessing Elements in Dictionaries

To access the value associated with a specific key, you use the key in square brackets [].

my_dict = {'name': 'Alice', 'age': 25, 'city': 'New York'}

# Accessing the value associated with the key 'name'


print(my_dict['name'])

[Link] 23/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
print(my_dict['age'])
print(my_dict['city'])

Alice
25
New York

my_dict = {'name': ['Alice', 'Brian', 'Lucy'], 'age': [25, 18, 32], 'city': ['New York', 'New York', 'Los Angeles']}
print(my_dict)

{'name': ['Alice', 'Brian', 'Lucy'], 'age': [25, 18, 32], 'city': ['New York', 'New York', 'Los Angeles']}

print(my_dict['name'][2])

Lucy

print(my_dict['city'][2])

Los Angeles

Handling Missing Keys

If you try to access a key that does not exist in the dictionary, Python will raise a KeyError.

To avoid this, you can use the .get() method which returns None (or a default value you provide) if the key is not found.

# Defining the dictionary


my_dict = {'name': 'Alice', 'age': 25, 'city': 'New York'}

print (my_dict['name'])

Alice

'''print(my_dict['hobby'])'''

'print(my_dict['hobby'])'

print(my_dict.get('hobby'))

None

Modifying Elements in Dictionaries

In Python, dictionaries are mutable, which means you can modify them after their creation. You can add new key-value pairs, update
existing ones, or remove them.

# Defining the dictionary


my_dict = {'name': 'Alice', 'age': 25, 'city': 'New York'}

# Adding a new key-value pair


my_dict['email'] = 'alice@[Link]'
print(my_dict)

{'name': 'Alice', 'age': 25, 'city': 'New York', 'email': 'alice@[Link]'}

# Updating an existing key-value pair


my_dict['city'] = 'Los Angeles'
print(my_dict)

{'name': 'Alice', 'age': 25, 'city': 'Los Angeles', 'email': 'alice@[Link]'}

# Removing a key-value pair: delete is abbreviated as the keyword del


del my_dict['city']
print(my_dict)

{'name': 'Alice', 'age': 25, 'email': 'alice@[Link]'}

Access Nested Dictionaries and Multiple Elements

# Sample dictionary with multiple elements, including nested dictionaries


data = {

[Link] 24/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
"user1": {
"name": "Alice",
"age": 30,
"hobbies": ["Reading", "Hiking", "Coding"]
},
"user2": {
"name": "Bob",
"age": 25,
"hobbies": ["Gaming", "Traveling"]
},
"user3": {
"name": "Charlie",
"age": 35,
"hobbies": ["Swimming", "Cooking"]
}
}
print(data)

{'user1': {'name': 'Alice', 'age': 30, 'hobbies': ['Reading', 'Hiking', 'Coding']}, 'user2': {'name': 'Bob', 'age': 25, 'hobbie

# Accessing data from the dictionary


# 1. Access data for a specific user
user1_data = data["user1"]
print(user1_data)

{'name': 'Alice', 'age': 30, 'hobbies': ['Reading', 'Hiking', 'Coding']}

user2_data = data["user2"]
print(user2_data)

{'name': 'Bob', 'age': 25, 'hobbies': ['Gaming', 'Traveling']}

# 2. Access a specific attribute of a user


user1_hobbies = data['user1']['hobbies']
print(user1_hobbies)

['Reading', 'Hiking', 'Coding']

# Access user2 age


user2_age = data['user2']['age']
print(user2_age)

25

# Update user2 age


data['user2']['age'] = 26
updated_user2_age = data['user2']['age']
print(updated_user2_age)

26

print(data)

{'user1': {'name': 'Alice', 'age': 30, 'hobbies': ['Reading', 'Hiking', 'Coding']}, 'user2': {'name': 'Bob', 'age': 26, 'hobbie

Control Flow in Python

Loop Control Statements Python provides several control statements to modify the behavior of loops, allowing for greater control over
how loops execute. These statements include break, continue, and else clauses with loops.

1. break Statement

The break statement is used to terminate the loop immediately, regardless of the loop's condition. Once the break statement is
encountered, the loop stops, and the execution continues with the statement immediately following the loop.

for num in range(10):


if num == 5:
break
print(num)

0
1
2
3

[Link] 25/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
4

2. continue Statement

The continue statement is used to skip the rest of the code inside the loop for the current iteration and proceed to the next iteration.
When continue is encountered, the loop's current iteration ends, and the next iteration begins.

for num in range(10):


if num % 2 == 0:
continue
print(num)

1
3
5
7
9

Start coding or generate with AI.

3. else Clause with Loops

The else block in a loop executes after the loop completes normally. If the loop is terminated by a break statement, the else block will not
be executed.

for num in range(5):


print(num)
else:
print("Loop completed")

0
1
2
3
4
Loop completed

for num in range(5):


if num == 3:
break
print(num)
else:
print("Loop completed")

0
1
2

Nested Control Flow

In Python, loops can be nested within other loops to perform more complex iterations. A nested loop is a loop inside another loop, where
the inner loop runs for each iteration of the outer loop.

for i in range(3):
for j in range(2):
print(f"i = {i}, j = {j}")

i = 0, j = 0
i = 0, j = 1
i = 1, j = 0
i = 1, j = 1
i = 2, j = 0
i = 2, j = 1

# Nested Control Flow Application

# 1. Multiplication Table

for i in range(1, 4):


for j in range(1, 4):
print(f"{i} * {j} = {i * j}")
print("-" * 10)

[Link] 26/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab

1 * 1 = 1
1 * 2 = 2
1 * 3 = 3
----------
2 * 1 = 2
2 * 2 = 4
2 * 3 = 6
----------
3 * 1 = 3
3 * 2 = 6
3 * 3 = 9
----------

# 2. Working with 2D Lists (Matrices)

matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]

for row in matrix:


for value in row:
print(value, end=" ")
print()

1 2 3
4 5 6
7 8 9

# 3. Pattern Generation

rows = 5
for i in range(1, rows + 1):
for j in range(1, i + 1):
print("*", end=" ")
print()

*
* *
* * *
* * * *
* * * * *

Start coding or generate with AI.

Nested while Loops

i = 0
while i < 3:
j = 0
while j < 2:
print(f"i = {i}, j = {j}")
j += 1
i += 1

i = 0, j = 0
i = 0, j = 1
i = 1, j = 0
i = 1, j = 1
i = 2, j = 0
i = 2, j = 1

for i in range(3):
j = 0
while j < 2:
print(f"i = {i}, j = {j}")
j += 1

i = 0, j = 0
i = 0, j = 1
i = 1, j = 0
i = 1, j = 1
i = 2, j = 0
i = 2, j = 1

[Link] 27/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab

Functions

Functions are a fundamental aspect of programming in Python. They allow you to group code into reusable blocks, making your programs
easier to read, maintain, and debug. Functions encapsulate logic, making it possible to call the same block of code multiple times within a
progr

1. Defining a Function

In Python, functions are defined using the def keyword followed by the function name and parentheses (). A function can have
parameters, which are specified within the parentheses. These parameters act as placeholders for the values that will be passed to the
function when it is called. Functions allow you to encapsulate code into reusable blocks, making your programs more modular and easier
to manage.

def function_name(parameters):
# code to execute
return value

def is the keyword used to define a function.


function_name is the name of the function.
parameters are optional and are placed inside the parentheses. If there are multiple parameters, they are separated by commas.
The colon : indicates the start of the function body.
The indented block of code below the definition is the function body, which contains the statements that will be executed when the
function is called.
The return statement is optional and is used to return a value from the function. If no return statement is provided, the function
returns None by default.

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

greet("Alice")
greet("Bob")

Hello, Alice!
Hello, Bob!

def add(a, b):


return a + b

result = add(3, 5)
print(result)

print(add(4, 7))

8
11

def product(a, b):


return a * b

result = product(3, 5)
print(result)

print(product(4, 7))

15
28

def division(a, b):


return a / b

result = division(15, 3)
print(result)

print(division(36, 6))

5.0
6.0

2. Function Parameters and Arguments

In Python, parameters and arguments are fundamental concepts in the context of functions. Understanding the difference between them
and how they are used can help you write more effective and reusable code.

[Link] 28/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
Parameters

Parameters are the variables listed inside the parentheses in the function definition. They act as placeholders for the values that will be
passed to the function when it is called. Example def add(a, b): return a + b In this example, a and b are parameters of the function add.

Arguments

Arguments are the actual values passed to the function when it is called. These values are assigned to the corresponding parameters.
Example result = add(3, 5) print(result)

In this example, 3 and 5 are arguments passed to the add function. These values are assigned to the parameters a and b, respectively.

Types of Function Parameters and Arguments

1. Positional Parameters

Positional parameters are the most common type. The arguments passed to the function are assigned to the parameters based on their
position.

def greet(first_name, last_name):


print(f"Hello, {first_name} {last_name}!")

greet("John", "Doe")

Hello, John Doe!

2. Default Parameters

You can provide default values for parameters. If no argument is passed, the default value is used.

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

greet()
greet("Alice")

Hello, World!
Hello, Alice!

3. Keyword Parameters

Keyword parameters allow you to specify arguments by parameter name, making function calls more readable.

def describe_pet(animal_type, pet_name):


print(f"I have a {animal_type} named {pet_name}.")

describe_pet(animal_type="dog", pet_name="Buddy")

I have a dog named Buddy.

4. Arbitrary Arguments (*args)

You can use *args to pass a variable number of positional arguments to a function.

del sum # This is to remove the user-defined sum variable we had used earlier in our code so that Python can access the built

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

result = sum_all(1, 2, 3, 4)
print(result)

10

5. Arbitrary Keyword Arguments (**kwargs)

You can use **kwargs to pass a variable number of keyword arguments to a function.

[Link] 29/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
def describe_person(**kwargs):
for key, value in [Link]():
print(f"{key}: {value}")

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

name: Alice
age: 30
city: New York

Return Statement

The return statement is a crucial feature in Python functions.


It allows a function to send a value (or multiple values) back to the caller.
This makes functions versatile and powerful, as they can perform calculations, process data, and then return the result to be used
elsewhere in the program.

Syntax

def function_name(parameters): # code to execute return value

return is followed by the value or expression that you want to send back to the caller.
If a function does not have a return statement, it returns None by default.

def square(number):
return number ** 2

result = square(4)
print(result)

16

def get_full_name(first_name, last_name):


full_name = f"{first_name} {last_name}"
return full_name

name = get_full_name("John", "Doe")


print(name)

John Doe

def get_full_name(first_name, last_name):


full_name = f"{first_name} {last_name}"
return full_name, len(full_name)

name, length = get_full_name("John", "Doe")


print(name)
print(length)

John Doe
8

# Functions can return different values based on conditions.

def evaluate_score(score):
if score >= 90:
return "A"
elif score >= 80:
return "B"
elif score >= 70:
return "C"
elif score >= 60:
return "D"
else:
return "F"

grade = evaluate_score(85)
print(grade)

# You can use return to exit a function early, before the end of its code block.

[Link] 30/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
def find_first_even(numbers):
for number in numbers:
if number % 2 == 0:
return number
return None

first_even = find_first_even([1, 3, 7, 9, 5])


print(first_even)

None

Variable Scope

Variable scope refers to the visibility and accessibility of variables within different parts of a program.
In Python, understanding variable scope is crucial for writing clear, maintainable, and bug-free code.

Types of Scope

1. Local scope
2. Global scope

1. Local Scope

Local scope refers to the scope of variables that are declared inside a function.
These variables are only accessible within that function and not outside of it.

Access Restriction: These local variables cannot be accessed outside the function in which they are defined.
If you try to access a local variable from outside its function, you will encounter a NameError.

def my_function():
example = 10 # example is a local variable
print(example) # This will print 10

my_function()

10

def my_function():
example = 10 # example is a local variable
print(example) # This will print 10

my_function()

# print(example) # Uncommenting this line will raise a NameError because x is not defined outside my_function

10

Advantages of Local Scope

Encapsulation: Local variables allow functions to be self-contained. This means that the internal workings of a function are hidden
from the rest of the program, promoting encapsulation.
Memory Management: Since local variables are destroyed after the function execution, it helps in efficient memory management.
Avoiding Naming Conflicts: Local variables enable the use of the same variable name in different functions without causing conflicts.

2. Global Scope

Global scope refers to variables that are defined outside of any function.
These variables are accessible from anywhere in the program, including inside functions.

x = 10 # x is a global variable
print(x) # This will also print 10, accessing the same global variable

10

x1 = 11
print(x1)

11

def my_function():
print(x) # This will print 10, accessing the global variable

[Link] 31/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab

my_function()

10

Advantages

Convenience: Global variables can be convenient for values that need to be accessed by multiple functions throughout the program.
Sharing Data: Global variables can be used to share data between different parts of the program without the need to pass
parameters.

Disadvantages

Unintended Modifications: Since global variables can be accessed and modified from anywhere in the program, there is a risk of
unintended modifications that can lead to bugs.
Reduced Modularity: Relying heavily on global variables can make the program less modular and harder to maintain, as functions
become dependent on external state.
Namespace Pollution: Excessive use of global variables can lead to a cluttered global namespace, increasing the likelihood of
variable name conflicts.

Lambda Functions

Lambda functions, also known as anonymous functions, are a concise way to create functions without using the def keyword and defining
a formal function block.

They are especially useful for short, simple operations where defining a full-fledged function using def would be overkill.

Syntax

The syntax of a lambda function is:

lambda arguments: expression

lambda is the keyword that introduces a lambda function.


arguments are the parameters of the function, similar to the parameters you would put in a def statement.
expression is a single expression that is evaluated and returned by the function.

def square(x):
result = x ** 2
return result
print(square(3))

square = lambda x: x ** 2
print(square(3))

Using Lambda Functions

Lambda functions are often used in situations where you need a simple function for a short period of time.

They are commonly used with functions like map(), filter(), and sorted().

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

[1, 4, 9, 16, 25]

[Link] 32/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
def multiply_by(n):
# Define an inner function using def instead of lambda
def multiplier(x):
return x * n
return multiplier

# Use the outer function to create multiplier functions


double = multiply_by(2)
triple = multiply_by(3)

# Test the inner functions


print(double(5))
print(triple(4))

10
12

def multiply_by(n):
# This lambda returns another function that multiplies its input by 'n'
return lambda x: x * n

# Use the outer function to create a multiplier function


double = multiply_by(2)
triple = multiply_by(3)

# Test the lambda functions


print(double(5))
print(triple(4))

10
12

Benefits of Lambda Functions

Conciseness: Lambda functions allow you to define functions in a compact manner.


Readability: They can make code more readable when the operation being performed is straightforward and doesn't require a
named function.

Limitations of Lambda Functions

Single Expression: Lambda functions can only contain a single expression. They are not suitable for complex logic or multi-step
operations i.e. you can't create inner functions using lambda functions.
Limited Use Cases: While powerful, lambda functions are best suited for situations where the function is short-lived and used in a
specific context.

Class Exercise

Object-Oriented Programming (OOP)

Object-Oriented Programming (OOP) is a paradigm that revolves around the concept of objects, which are instances of classes.

In Python, OOP is a powerful way to structure and organize code, offering benefits such as modularity, reusability, and ease of
maintenance.

Importance of OOP

1. Understanding Libraries and Frameworks - Many popular libraries and frameworks used in data science, such as Pandas, NumPy,
Scikit-learn, and TensorFlow, are built using OOP principles. Understanding OOP helps students better grasp these tools and
libraries, enabling them to leverage their full capabilities.
2. Modular Code Design - OOP promotes modular code design, which is crucial for building complex data pipelines, machine learning
models, and data processing systems. It encourages encapsulation, abstraction, polymorphism, and inheritance, making code more
organized and maintainable.
3. Custom Classes and Data Structures - Data scientists often need to create custom classes and data structures to represent specific
data entities or models. For example, a class to encapsulate a machine learning model with training, prediction, and evaluation
methods. OOP provides a structured approach to designing and implementing such classes.
4. Collaboration with Software Engineers - Data scientists often collaborate with software engineers and developers in building
production-grade systems. Knowledge of OOP facilitates effective communication and collaboration with engineering teams,
ensuring seamless integration of data science solutions into larger software projects.
5. Career Flexibility and Versatility - Data scientists who are proficient in OOP are better positioned to transition into roles that require
software development skills or move into more technical leadership roles within data science teams. It broadens their career

[Link] 33/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
opportunities beyond traditional data analysis and modeling.

Key Concepts in OOP

1. Class

A class in Python serves as a blueprint or template for creating objects.


It defines the structure and behavior that objects of that class will have.
The class encapsulates data (attributes) and behaviors (methods) that define the characteristics and actions of its objects.

Syntax

class ClassName: def init(self, param1, param2, ...): self.attribute1 = param1 self.attribute2 = param2 # More attributes

def method1(self):
# Method implementation
pass

def method2(self):
# Method implementation
pass

class ClassName: Defines a new class named ClassName.


def init(self, param1, param2, ...): Constructor method (initializer) called when an object of the class is instantiated (init is short for
initialization). It initializes the object's attributes.

self.attribute1 = param1: Defines an instance attribute attribute1 and initializes it with param1.
self.attribute2 = param2: Defines another instance attribute attribute2 and initializes it with param2.

Methods (def method1(self):, def method2(self):): Functions defined inside the class that define the behavior of the class's objects.
These methods can access and manipulate the object's attributes using the self parameter.

class Car:
def __init__(self, brand, model):
[Link] = brand
[Link] = model

def display_info(self):
print(f"Car: {[Link]} {[Link]}")

# Usage
my_car = Car("Toyota", "Camry")
my_car.display_info()

my_car1 = Car("Ford", "Mustang Mach-E")


my_car1.display_info()

Car: Toyota Camry


Car: Ford Mustang Mach-E

The Main Principles of Object-Oriented Programming (OOP)

1. Abstraction

Abstraction is a fundamental principle of Object-Oriented Programming (OOP) that simplifies complex systems by hiding the underlying
implementation details and exposing only the necessary features to the user. This allows developers to work with higher-level concepts
without needing to understand the intricate workings of these concepts.

Definition

Abstraction involves hiding the complex implementation details and exposing only the essential features of an object. It allows developers
to focus on what an object does rather than how it does it.

Achieving Abstraction in Python

In Python, abstraction can be achieved through the use of abstract classes and methods. The abc (Abstract Base Classes) module in
Python provides the infrastructure for defining abstract base classes.

Using Abstract Classes and Methods

An abstract class can contain one or more abstract methods. An abstract method is a method that is declared but contains no
implementation. Concrete subclasses of the abstract class are required to implement these abstract methods.

[Link] 34/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
from abc import ABC, abstractmethod

class Animal(ABC):
@abstractmethod
def sound(self):
pass

class Dog(Animal):
def sound(self):
return "Bark"

class Cat(Animal):
def sound(self):
return "Meow"

class Lion(Animal):
def sound(self):
return 'Roar'

# Abstract class cannot be instantiated


# animal = Animal() # This will raise an error

dog = Dog()
cat = Cat()
lion = Lion()

print([Link]())
print([Link]())
print([Link]())

Bark
Meow
Roar

Explanation of the Example

Abstract Class Definition

Animal is an abstract class that inherits from ABC (Abstract Base Class). It has an abstract method sound decorated with
@abstractmethod. This method does not have any implementation.

Concrete Class Implementation

Dog and Cat are concrete classes that inherit from the Animal abstract class. Both classes provide their own implementation of the sound
method.

Instantiation and Usage

An abstract class cannot be instantiated directly. Attempting to create an instance of Animal will result in an error.

Instances of the Dog and Cat classes can be created, and their sound methods can be called to return "Bark" and "Meow" respectively.

Benefits of Abstraction

Focus on What an Object Does - By hiding the implementation details, abstraction allows developers to focus on what an object does
rather than how it does it. This simplifies the development process.

Promotes Reusability - Abstract classes can define a template for a group of related classes. This promotes code reuse by providing a
common interface for different implementations.

Improves Code Maintainability - By separating the interface from the implementation, abstraction makes it easier to modify or extend the
code. Changes to the implementation do not affect the code that relies on the abstract interface.

Encourages Modular Design - Abstraction helps in designing modular systems where different components interact through well-defined
interfaces. This modularity enhances the maintainability and scalability of the system.

Practical Use Cases of Abstraction

Software Libraries - Abstract classes and methods are commonly used in software libraries to define common interfaces. Users of the
library interact with these interfaces without needing to know the underlying implementation.

Frameworks - Frameworks often use abstraction to define the basic structure and behavior of applications. Developers extend abstract
classes to create specific functionality.

Plugins and Extensions - Abstraction is used to define plugin interfaces. Plugins implement these interfaces to extend the functionality of
an application.

2. Encapsulation

[Link] 35/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
class Car:
def __init__(self, model, year):
[Link] = model
self.__year = year # Private attribute

def display_info(self):
return f"Model: {[Link]}, Year: {self.__year}"

def set_year(self, year):


if year > 1885: # The first car was invented around 1885
self.__year = year
else:
print("Invalid year")

car = Car("Toyota", 2020)


print(car.display_info())

car.set_year(1990)
print(car.display_info())

# Trying to access the private attribute directly


# print(car.__year) # This will raise an AttributeError

Model: Toyota, Year: 2020


Model: Toyota, Year: 1990

Explanation of the Example

Class Definition

The Car class is defined with two attributes: model and __year. The __year attribute is private, indicated by the double underscore prefix.

Constructor Method

The init method initializes the model and __year attributes when a new instance of the Car class is created.

Display Info Method

The display_info method returns a string that includes the model and year of the car. This method provides controlled access to the
private __year attribute.

Set Year Method

The set_year method allows for setting the year of the car, but only if the year is greater than 1885. This method ensures that the __year
attribute is updated in a controlled manner.

Accessing Private Attributes

Direct access to the private __year attribute from outside the class is not allowed. Attempting to do so will raise an AttributeError.

The private attribute can only be accessed through the public methods display_info and set_year.

Start coding or generate with AI.

Benefits of Encapsulation

1. Data Protection - Encapsulation protects an object's internal state from unintended or harmful interference by restricting direct
access to its attributes. This ensures that the object’s data is always in a valid state.

2. Controlled Access - By providing getter and setter methods (accessors and mutators), encapsulation allows controlled access to an
object's [Link] ensures that any changes to the attributes follow the rules defined within these methods.

3. Modularity - Encapsulation helps in creating modular code where each class is responsible for its own data and behavior. This
modularity makes the code easier to understand, maintain, and extend.

4. Improved Debugging - With encapsulation, you can add logging or validation logic within the setter methods to track changes and
identify bugs more easily.

Practical Use Cases of Encapsulation

1. Data Validation - Encapsulation is commonly used to validate data before it is set on an object. This ensures that the object’s state
remains consistent and valid.

2. Security - Encapsulation provides a layer of security by hiding sensitive data from external access. Only trusted methods within the
class can access and modify this data.

3. API Design - When designing APIs, encapsulation helps in exposing only the necessary parts of an object, hiding the implementation
details. This makes the API easier to use and reduces the risk of misuse.

[Link] 36/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab

**3. Inheritance **

Inheritance allows a class (subclass/derived class) to inherit attributes and methods from another class (superclass/base class).

It facilitates code reuse and supports the hierarchical classification of classes.

# Superclass Definition - Vehicle is the superclass with two attributes: brand and model. It includes a method display_info tha

class Vehicle:
def __init__(self, brand, model):
[Link] = brand
[Link] = model

def display_info(self):
return f"Brand: {[Link]}, Model: {[Link]}"

# Subclass Definition - Car is the subclass that inherits from the Vehicle class. It has an additional attribute year and a mod

class Car(Vehicle):
def __init__(self, brand, model, year):
super().__init__(brand, model)
[Link] = year

def display_info(self):
return f"Brand: {[Link]}, Model: {[Link]}, Year: {[Link]}"

car = Car("Honda", "Civic", 2022)


print(car.display_info())

Brand: Honda, Model: Civic, Year: 2022

class Truck(Vehicle):
def __init__(self, brand, model, weight_capacity):
super().__init__(brand, model)
self.weight_capacity = weight_capacity

def display_info(self):
return f"Brand: {[Link]}, Model: {[Link]}, Weight_Capacity: {self.weight_capacity}"

truck = Truck("Ford", "Mach E", 951)


print(truck.display_info())

Brand: Ford, Model: Mach E, Weight_Capacity: 951

Benefits of Inheritance

1. Code Reuse - Inheritance promotes code reuse by allowing a subclass to inherit and use the attributes and methods of its
superclass. This reduces code duplication.
2. Hierarchical Classification - Inheritance supports the organization of classes in a hierarchical manner. This makes it easier to
understand and manage complex systems.
3. Extensibility - Subclasses can extend or modify the behavior of the superclass by adding new attributes and methods or by
overriding existing ones.
4. Maintainability - Changes made to the superclass are automatically inherited by the subclasses. This centralizes common behavior,
making the code easier to maintain.

Practical Use Cases of Inheritance

Software Libraries - Inheritance is commonly used in software libraries to create a base class with common functionality that can be
extended by other classes.
Frameworks - Frameworks use inheritance to provide a base class that developers can extend to create specific functionality for
their applications.
User Interface Components - Inheritance is often used to create a base class for UI components with common behavior, which can
be extended to create specific types of components.
Domain Models - In domain modeling, inheritance helps in representing real-world hierarchies and relationships between entities.

# Multiple Inheritance

class Flyable:
def fly(self):
return "Flying"

class Swimmable:
def swim(self):
return "Swimming"

[Link] 37/38
9/9/25, 8:14 PM Python_Programming.ipynb - Colab
class Duck(Flyable, Swimmable):
pass

duck = Duck()

print([Link]())
print([Link]())

Flying
Swimming

class Eagle(Flyable):
pass

eagle = Eagle()

print([Link]())

Flying

4. Polymorphism

Polymorphism refers to the ability of different classes to be treated as instances of the same class through a common interface.

It allows methods to be called on objects of different classes and have them behave differently based on their own implementation.

class Bird:
def fly(self):
return "Bird is flying"

class Airplane:
def fly(self):
return "Airplane is flying"

class Kite:
def fly(self):
return "Kite is flying"

# Polymorphic function
def let_it_fly(flying_object):
print(flying_object.fly())

bird = Bird()
airplane = Airplane()
kite = Kite()

let_it_fly(bird)
let_it_fly(airplane)
let_it_fly(kite)

Bird is flying
Airplane is flying
Kite is flying

Benefits of Polymorphism

1. Code Flexibility - Polymorphism increases flexibility in the code by allowing a single function to operate on objects of different
classes.
2. Ease of Maintenance - Polymorphic behavior makes the code easier to maintain and extend, as new classes with common interfaces
can be added without modifying existing functions.
3. Enhanced Readability - Using polymorphism, code readability is improved as the same operation can be applied to different objects
in a straightforward manner.
4. Dynamic Behavior - Polymorphism enables dynamic behavior where the appropriate method is called based on the object's class at
runtime, rather than compile-time.

Practical Use Cases of Polymorphism

[Link] 38/38

You might also like