0% found this document useful (0 votes)
10 views197 pages

Python Handnote 1

This document provides an overview of Python syntax, comments, variables, and string manipulation. It covers essential rules, best practices, and examples for writing Python code, including variable types, naming conventions, and string formatting techniques. The notes serve as a foundational guide for understanding and practicing Python programming.

Uploaded by

darkknight18427
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
0% found this document useful (0 votes)
10 views197 pages

Python Handnote 1

This document provides an overview of Python syntax, comments, variables, and string manipulation. It covers essential rules, best practices, and examples for writing Python code, including variable types, naming conventions, and string formatting techniques. The notes serve as a foundational guide for understanding and practicing Python programming.

Uploaded by

darkknight18427
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
Download as pdf or txt
You are on page 1/ 197

Chapter 1

Python is a high-level programming language known for its simplicity and readability. This note
covers Python syntax and comments to help you in your studies.

1. Python Syntax

a. Basic Rules

1. Case Sensitivity: Python is case-sensitive, meaning Variable and variable are treated
as different identifiers.

name = "Alice"
Name = "Bob"
print(name) # Outputs: Alice
print(Name) # Outputs: Bob

2. No Semicolons: Statements in Python do not need a semicolon (;). New lines separate
the statements.

print("Hello") # Correct
print("Hello"); # Also works but not recommended

3. Indentation: Python uses indentation to define code blocks (like loops or functions),
instead of curly braces {}.

if True:
print("This is indented") # Indented code block

4. Dynamic Typing: Variables do not need explicit type declaration.

x = 5 # Integer
y = "Hello" # String

b. Writing Statements

 Single-line Statements: Written on one line.

print("This is a single-line statement")

 Multi-line Statements: Use a backslash (\) to extend statements across lines.

total = 5 + 6 + 7 + \8 + 9
print(total)
 Grouping Statements: Use parentheses (), brackets [], or braces {} to write multi-line
statements without a backslash.

numbers = [1, 2, 3,4, 5, 6]


print(numbers)

c. Input and Output

 Output: Use the print() function.

print("Hello, World!")

 Input: Use the input() function.

name = input("Enter your name: ")


print("Hello, " + name)

2. Comments in Python

Comments are non-executable lines in a program used to explain code or make notes.

a. Types of Comments

1. Single-line Comments: Begin with a hash symbol (#).

# This is a single-line comment


print("Hello, World!") # This comment is inline

2. Multi-line Comments (Docstrings): Use triple quotes (""" or ''') for multi-line
comments.

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

b. Uses of Comments

 Explain code functionality:

# Calculate the sum of two numbers


a = 10
b = 20
print(a + b)

 Disable code temporarily:


# print("This line will not execute")
print("This line will execute")

Document functions or classes:

 def greet(name):
"""
This function greets a person by their name.
"""
print(f"Hello, {name}!")

Good Practices

1. Write meaningful comments to improve code readability.


2. Avoid overusing comments; let the code speak for itself when possible.
3. Maintain consistent indentation and commenting style.

These notes provide a foundation for understanding Python syntax and comments. Practice
writing Python code and comments to develop fluency!
Variables in Python are used to store data values. A variable acts as a container for information
that can be referenced and manipulated in a program.

1. Characteristics of Python Variables

1. Dynamic Typing:
o Python variables do not require explicit type declaration.
o The data type is determined based on the assigned value.

x = 10 # Integer
y = 3.14 # Float
z = "Hello" # String

2. Case Sensitivity:
o Variables are case-sensitive.
o For example, age and Age are different variables.

age = 25
Age = 30
print(age) # Outputs: 25
print(Age) # Outputs: 30

3. No Need for Explicit Declaration:


o Variables are created automatically when a value is assigned to them.

name = "Alice"
print(name) # Outputs: Alice

4. Can Change Type Dynamically:


o The type of a variable can be changed by assigning a value of a different type.

x = 10 # Integer
x = "Text" # Now a String
print(x) # Outputs: Text

2. Rules for Naming Variables

1. Start with a Letter or Underscore:


o Variables must begin with a letter (a-z, A-Z) or an underscore (_).

_value = 10
name = "John"
2. Cannot Start with a Number:
o Variable names cannot begin with a digit.

# 1name = "Error" # This will raise a SyntaxError


name1 = "Valid"

3. Use Letters, Numbers, and Underscores Only:


o Names can only contain alphanumeric characters and underscores (_).

user_name = "Alice"
user123 = "Bob"

4. Cannot Use Reserved Keywords:


o Reserved words like if, while, class, etc., cannot be used as variable names.

# if = 10 # This will raise a SyntaxError


value = 10 # Valid

5. Be Descriptive:
o Use meaningful names for better readability.

score = 95 # Clear
x = 95 # Ambiguous

3. Variable Assignment

1. Single Assignment:
o Assign a single value to a variable.

x = 5

2. Multiple Assignment:
o Assign the same value to multiple variables.

a = b = c = 10
print(a, b, c) # Outputs: 10 10 10

3. Multiple Variables, Multiple Values:


o Assign different values to multiple variables in one line.

x, y, z = 1, 2, 3
print(x, y, z) # Outputs: 1 2 3

4. Variable Types

Python variables can store values of different data types. Some commonly used types are:
1. Integer:

age = 25

2. Float:

pi = 3.14159

3. String:

name = "Alice"

4. Boolean:

is_active = True

5. List:

numbers = [1, 2, 3, 4, 5]

6. Tuple:

coordinates = (10, 20)

7. Dictionary:

user = {"name": "Alice", "age": 25}

5. Variable Scope

1. Local Scope:
o Variables declared inside a function are local to that function.

def my_function():
x = 10 # Local variable
print(x)
my_function()
# print(x) # Raises NameError, x is not accessible outside the
function

2. Global Scope:
o Variables declared outside functions are global and accessible throughout the
program.

x = 10 # Global variable
def my_function():
print(x)
my_function() # Outputs: 10
6. Constants

In Python, constants are variables whose values should not change. By convention, they are
written in uppercase.

PI = 3.14159
GRAVITY = 9.8

Although Python does not enforce immutability, treating such variables as constants is a good
practice.

Good Practices for Variables

1. Use descriptive names for clarity.


2. Follow naming conventions (snake_case for variables).
3. Avoid overwriting built-in function names (e.g., max, list).
4. Keep variable scope minimal to prevent unintended side effects.

These notes provide a comprehensive guide to understanding Python variables. Practice using
variables in different contexts to strengthen your programming skills!
Mutability refers to whether or not an object’s value can be changed after it is created. In
Python, objects are categorized as mutable or immutable.

1. Mutable vs Immutable Objects

a.Mutable Objects

 Objects whose values can be modified after creation.


 Changes happen in place, and the object retains its identity (memory address).
 Examples: list, dict, set, bytearray.

Example:

python
Copy code
my_list = [1, 2, 3]
my_list[0] = 10 # Modifies the first element
print(my_list) # Output: [10, 2, 3]

b.Immutable Objects

 Objects whose values cannot be modified after creation.


 Any "modification" creates a new object with a different identity.
 Examples: int, float, str, tuple, frozenset.

Example:

python
Copy code
my_string = "Hello"
new_string = my_string + " World" # Creates a new string
print(my_string) # Output: "Hello"
print(new_string) # Output: "Hello World"
Built-in Data Types
In programming, data type is an important concept.

Variables can store data of different types, and different types can do different
things.

Python has the following data types built-in by default, in these categories:

Text Type: str

Numeric Types: int, float, complex

Sequence Types: list, tuple, range

Mapping Type: dict

Set Types: set, frozenset

Boolean Type: bool

Binary Types: bytes, bytearray, memoryview

None Type: NoneType

Getting the Data Type


You can get the data type of any object by using the type() function:
x = 5
print(type(x))

Strings in python are surrounded by either single quotation marks, or double


quotation marks.

'hello' is the same as "hello".

You can display a string literal with the print() function:

Example
print("Hello")
print('Hello')

Quotes Inside Quotes


You can use quotes inside a string, as long as they don't match the quotes
surrounding the string:

Example
print("It's alright")
print("He is called 'Johnny'")
print('He is called "Johnny"')

Assign String to a Variable


Assigning a string to a variable is done with the variable name followed by an
equal sign and the string:

Example
a = "Hello"
print(a)
Multiline Strings
You can assign a multiline string to a variable by using three quotes:

Example
You can use three double quotes:

a = """Lorem ipsum dolor sit amet,


consectetur adipiscing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua."""
print(a)

Or three single quotes:

Example
a = '''Lorem ipsum dolor sit amet,
consectetur adipiscing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.'''
print(a)

Note: in the result, the line breaks are inserted at the same position as in the
code.

Strings are Arrays


Like many other popular programming languages, strings in Python are arrays
of bytes representing unicode characters.

However, Python does not have a character data type, a single character is
simply a string with a length of 1.

Square brackets can be used to access elements of the string.


Example
Get the character at position 1 (remember that the first character has the
position 0):

a = "Hello, World!"
print(a[1])

Looping Through a String


Since strings are arrays, we can loop through the characters in a string, with
a for loop.

Example
Loop through the letters in the word "banana":

for x in "banana":
print(x)

String Length
To get the length of a string, use the len() function.

Example
The len() function returns the length of a string:

a = "Hello, World!"
print(len(a))

Check String
To check if a certain phrase or character is present in a string, we can use the
keyword in.

Example
Check if "free" is present in the following text:
txt = "The best things in life are free!"
print("free" in txt)

Use it in an if statement:

Example
Print only if "free" is present:

txt = "The best things in life are free!"


if "free" in txt:
print("Yes, 'free' is present.")

Check if NOT
To check if a certain phrase or character is NOT present in a string, we can use
the keyword not in.

Example
Check if "expensive" is NOT present in the following text:

txt = "The best things in life are free!"


print("expensive" not in txt)

Use it in an if statement:

Example
print only if "expensive" is NOT present:

txt = "The best things in life are free!"


if "expensive" not in txt:
print("No, 'expensive' is NOT present.")
1.Python - Slicing Strings

You can return a range of characters by using the slice syntax.

Specify the start index and the end index, separated by a colon, to return a part
of the string.

Example :

Get the characters from position 2 to position 5 (not included):

b = "Hello, World!"
print(b[2:5])

Note: The first character has index 0.

Slice From the Start


By leaving out the start index, the range will start at the first character:

Example
Get the characters from the start to position 5 (not included):

b = "Hello, World!"
print(b[:5])

Slice To the End

By leaving out the end index, the range will go to the end:

Example
Get the characters from position 2, and all the way to the end:
b = "Hello, World!"
print(b[2:])

Negative Indexing
Use negative indexes to start the slice from the end of the string:

Example
Get the characters:

From: "o" in "World!" (position -5)

To, but not included: "d" in "World!" (position -2):

b = "Hello, World!"
print(b[-5:-2])

2.Python - Modify Strings


Python has a set of built-in methods that you can use on strings.

a.Upper Case

The upper() method returns the string in upper case:

a = "Hello, World!"
print(a.upper())

b.Lower Case

The lower() method returns the string in lower case:

a = "Hello, World!"
print(a.lower())

c.Remove Whitespace
Whitespace is the space before and/or after the actual text, and very often you
want to remove this space.

The strip() method removes any whitespace from the beginning or the end:

a = " Hello, World! "


print(a.strip()) # returns "Hello, World!"

d.Replace String

The replace() method replaces a string with another string:

a = "Hello, World!"
print(a.replace("H", "J"))

e.Split String
The split() method returns a list where the text between the specified separator
becomes the list items.

The split() method splits the string into substrings if it finds instances of the
separator:

a = "Hello, World!"
print(a.split(",")) # returns ['Hello', ' World!']

3.Python - String Concatenation

To concatenate, or combine, two strings you can use the + operator.

Merge variable a with variable b into variable c:

a = "Hello"
b = "World"
c = a + b
print(c)
To add a space between them, add a " ":

a = "Hello"
b = "World"
c = a + " " + b
print(c)

4. String Formatting in Python


String formatting in Python is a technique used to inject dynamic content (like variables or
expressions) into strings. Python offers several ways to format strings, ranging from older
methods to more modern approaches that are more readable and flexible.

1. Old-Style String Formatting (% Operator)

This is the classic method of formatting strings in Python, commonly known as the percent
formatting.

1.1 Syntax

python
CopyEdit
"string with %s" % value

 %s: A placeholder for a string.


 %d: Placeholder for an integer.
 %f: Placeholder for a float.

1.2 Examples

python
CopyEdit
name = "Alice"
age = 25
height = 5.6

# Formatting with %
formatted_string = "Name: %s, Age: %d, Height: %.1f" % (name, age, height)
print(formatted_string)

Output:

yaml
CopyEdit
Name: Alice, Age: 25, Height: 5.6

Here, %s is replaced with the string Alice, %d is replaced with the integer 25, and %.1f is used to
format the floating-point number 5.6 with one decimal place.

2. str.format() Method (Introduced in Python 2.7/3.0)

The str.format() method is more versatile and easier to read than the older % formatting. It
uses curly braces {} as placeholders and allows you to pass values into the string via the
format() method.

2.1 Basic Syntax

python
CopyEdit
"string with {}".format(value)

2.2 Examples

python
CopyEdit
name = "Bob"
age = 30
height = 6.2

# Basic usage
formatted_string = "Name: {}, Age: {}, Height: {}".format(name, age, height)
print(formatted_string)

Output:

yaml
CopyEdit
Name: Bob, Age: 30, Height: 6.2

2.3 Positional and Keyword Arguments

You can pass arguments by position or by name for better readability.

python
CopyEdit
# Positional
formatted_string = "Name: {}, Age: {}, Height: {}".format(name, age, height)
print(formatted_string)

# Keyword arguments
formatted_string = "Name: {0}, Age: {1}, Height: {2}".format(name, age,
height)
print(formatted_string)
# Using named placeholders
formatted_string = "Name: {name}, Age: {age}, Height:
{height}".format(name="Charlie", age=28, height=5.9)
print(formatted_string)

Output:

yaml
CopyEdit
Name: Bob, Age: 30, Height: 6.2
Name: Bob, Age: 30, Height: 6.2
Name: Charlie, Age: 28, Height: 5.9

3. F-Strings (Formatted String Literals) (Introduced in Python 3.6)

F-strings are the most modern and preferred method for string formatting in Python. They
provide a way to embed expressions inside string literals using {} and the f prefix before the
string.

3.1 Syntax

python
CopyEdit
f"string with {expression}"

3.2 Examples

python
CopyEdit
name = "David"
age = 40
height = 5.8

# Using f-strings
formatted_string = f"Name: {name}, Age: {age}, Height: {height}"
print(formatted_string)

Output:

yaml
CopyEdit
Name: David, Age: 40, Height: 5.8

3.3 Using Expressions Inside F-strings

You can also perform operations directly within the curly braces.

python
CopyEdit
x = 5
y = 10
formatted_string = f"The sum of {x} and {y} is {x + y}"
print(formatted_string)

Output:

python
CopyEdit
The sum of 5 and 10 is 15

3.4 Formatting Numbers with F-strings

F-strings also support advanced formatting for numbers, such as controlling the number of
decimal places.

python
CopyEdit
pi = 3.1415926535
formatted_string = f"Pi to 2 decimal places: {pi:.2f}"
print(formatted_string)

Output:

vbnet
CopyEdit
Pi to 2 decimal places: 3.14

 :.2f ensures that the number is formatted as a float with 2 decimal places.

4. Advanced String Formatting (Formatting with Width, Alignment, Padding)

Python provides powerful options for controlling the width, alignment, and padding of string
elements in a formatted string.

4.1 Specifying Width

You can specify the minimum width of a string or number:

python
CopyEdit
name = "Alice"
formatted_string = f"{name:10}" # Right-aligned, width of 10
print(f"'{formatted_string}'")

Output:

arduino
CopyEdit
'Alice '

4.2 Left and Center Alignment


You can also left-align or center-align text:

python
CopyEdit
# Left align
formatted_string = f"{name:<10}"
print(f"'{formatted_string}'")

# Center align
formatted_string = f"{name:^10}"
print(f"'{formatted_string}'")

Output:

arduino
CopyEdit
'Alice '
' Alice '

4.3 Padding with Specific Characters

You can pad a string with any character (default is a space):

python
CopyEdit
formatted_string = f"{name:.^10}" # Centered, with dot padding
print(f"'{formatted_string}'")

Output:

arduino
CopyEdit
'..Alice...'

4.4 Formatting Numbers with Commas

To format numbers with commas for thousands, use:

python
CopyEdit
large_number = 1000000
formatted_string = f"{large_number:,}"
print(formatted_string)

Output:

CopyEdit
1,000,000

Summary of String Formatting Methods


1. Old-Style (% Formatting):
o Simple, but less readable and flexible.
o Example: "Hello, %s!" % name
2. str.format():
o More readable and flexible than % formatting.
o Supports positional and keyword arguments.
o Example: "Hello, {0}!".format(name)
3. F-Strings (Python 3.6+):
o The most modern and preferred way.
o Allows inline expressions and concise formatting.
o Example: f"Hello, {name}!"
4. Advanced Formatting:
o Specify width, alignment, padding, and number formatting with :<, :^, :10, etc.
o Example: f"{pi:.2f}" for floating-point formatting.

4.Python Escape Characters


In Python, escape characters allow you to include special characters in strings that would
otherwise be difficult or impossible to represent. They are written using a backslash (\) followed
by a specific character.

Common Escape Characters


Escape
Meaning Example Output
Character
\' Single quote 'Python\'s' → Python's
\" Double quote "She said, \"Hi!\"" → She said, "Hi!"
\\ Backslash C:\\Path → C:\Path
\n Newline Hello\nWorld → Hello (new line) World
\t Tab Hello\tWorld → Hello World
\r Carriage return Hello\rWorld → World (overwrites Hello)
\b Backspace He\bllo → Helo
\f Form feed Moves to the next page in output. Rarely used.
Hello\vWorld (spacing effect depends on the
\v Vertical tab
environment)
\ooo Octal value character \101 → A (ASCII value in octal)
Hexadecimal value
\xhh \x41 → A (ASCII value in hex)
character
Examples of Escape Characters
# Using escape characters in strings
print("Python\'s escape characters")
# Output: Python's escape characters

print("New line example:\nHello, World!")


# Output:
# New line example:
# Hello, World!

print("Tabbed example:\tPython Tutor")


# Output: Tabbed example: Python Tutor

print("Backslash example: C:\\Users\\Admin")


# Output: Backslash example: C:\Users\Admin

Key Points

1. Escape characters are always preceded by a backslash (\).


2. They allow you to include special symbols, whitespace, and control sequences in strings.
3. Strings with escape characters can be written in single or double quotes.
4. Use raw strings (prefix with r) if you want to ignore escape sequences:
5. print(r"C:\Users\Admin")
6. # Output: C:\Users\Admin

Practice Questions:

1. Write a Python program to print the following:


2. Path: C:\new_folder\file.txt
3. Use \n and \t to format a multi-line string displaying your name and hobbies.
4. Experiment with \b and observe its effect in different strings.

5.String methods
In Python, string methods are built-in functions associated with string objects that allow you to
perform various operations on strings. These methods help manipulate and analyze strings
efficiently, such as modifying case, finding substrings, splitting strings, or replacing parts of a
string.

Commonly Used String Methods


Here is a list of frequently used string methods in Python with descriptions and examples:

Method Description Example Output


str.upper()
Converts all characters "hello".upper() 'HELLO'
to uppercase.
str.lower()
Converts all characters "HELLO".lower() 'hello'
to lowercase.
str.capitalize()
Capitalizes the first "python".capitalize() 'Python'
character of the string.
Converts the first
'Hello
str.title() character of each word "hello world".title()
World'
to uppercase.
str.strip()
Removes leading and " hello ".strip() 'hello'
trailing whitespace.
str.lstrip()
Removes leading " hello".lstrip() 'hello'
whitespace.
str.rstrip()
Removes trailing "hello ".rstrip() 'hello'
whitespace.
"hello
str.replace()
Replaces a substring world".replace("world",
'hello
with another substring. Python'
"Python")
Returns the index of the
str.find() first occurrence of a "hello".find("l") 2
substring.
Similar to find(), but
str.index() raises an error if not "hello".index("l") 2
found.
str.split()
Splits the string into a "a,b,c".split(",")
['a',
list based on a delimiter. 'b', 'c']

str.join()
Joins a list of strings into ",".join(['a', 'b', 'c']) 'a,b,c'
a single string.
Checks if the string
str.startswith() starts with a specified "hello".startswith("he") True
prefix.
str.endswith()
Checks if the string ends "hello".endswith("lo") True
with a specified suffix.
str.isdigit()
Checks if all characters "12345".isdigit() True
are digits.
str.isalpha()
Checks if all characters "hello".isalpha() True
are alphabetic.
str.isalnum()
Checks if all characters "hello123".isalnum() True
are alphanumeric.
Method Description Example Output
str.isspace()
Checks if all characters " ".isspace() True
are whitespace.
Swaps uppercase to
str.swapcase() lowercase and vice "Hello".swapcase() 'hELLO'
versa.
str.zfill(width)
Pads the string with "42".zfill(5) '00042'
zeros on the left.
str.center(width)
Centers the string within "hello".center(10) ' hello '
the specified width.
str.count()
Counts occurrences of a "banana".count("a") 3
substring.

Focus on Commonly Used Methods

Start with the most frequently used methods, which are helpful in day-to-day coding:

 upper(), lower(), strip() for basic text formatting.


 replace(), find(), split(), and join() for text manipulation.
 startswith(), endswith(), isdigit() for validations.
There are three numeric types in Python:

 int (Integers)
 float
 complex

Variables of numeric types are created when you assign a value to them:

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

To verify the type of any object in Python, use the type() function:

Example
print(type(x))
print(type(y))
print(type(z))

a.Int
Int, or integer, is a whole number, positive or negative, without decimals, of
unlimited length.

Example
Integers:

x = 1
y = 35656222554887711
z = -3255522

print(type(x))
print(type(y))
print(type(z))

b.Float
Float, or "floating point number" is a number, positive or negative, containing
one or more decimals.

Example
Floats:

x = 1.10
y = 1.0
z = -35.59

print(type(x))
print(type(y))
print(type(z))

Float can also be scientific numbers with an "e" to indicate the power of 10.

Example
Floats:

x = 35e3
y = 12E4
z = -87.7e100

print(type(x))
print(type(y))
print(type(z))
c.Complex
Complex numbers are written with a "j" as the imaginary part:

Example
Complex:

x = 3+5j
y = 5j
z = -5j

print(type(x))
print(type(y))
print(type(z))

1.Type Conversion
You can convert from one type to another with the int(), float(),
and complex() methods:

Example
Convert from one type to another:

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

#convert from int to float:


a = float(x)

#convert from float to int:


b = int(y)

#convert from int to complex:


c = complex(x)

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

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

Note: You cannot convert complex numbers into another number type.

2.Random Number
Python does not have a random() function to make a random number, but Python
has a built-in module called random that can be used to make random numbers:

Example
Import the random module, and display a random number between 1 and 9:

import random

print(random.randrange(1, 10))

In our Random Module Reference you will learn more about the Random
module.
Booleans represent one of two values: True or False.

In programming you often need to know if an expression is True or False.

You can evaluate any expression in Python, and get one of two
answers, True or False.

When you compare two values, the expression is evaluated and Python returns
the Boolean answer:

Example
print(10 > 9) #output: True
print(10 == 9) #output: False
print(10 < 9) #Output: False

When you run a condition in an if statement, Python returns True or False:

Example
Print a message based on whether the condition is True or False:

a = 200
b = 33

if b > a:
print("b is greater than a")
else:
print("b is not greater than a")
#Output: b is not greater than a

Evaluate Values and Variables


The bool() function allows you to evaluate any value, and give
you True or False in return,
Example
Evaluate a string and a number:

print(bool("Hello")) # output: True


print(bool(15)) # output: True

Example
Evaluate two variables:

x = "Hello"
y = 15

print(bool(x)) # output: True


print(bool(y)) # output: True

Most Values are True


Almost any value is evaluated to True if it has some sort of content.

Any string is True, except empty strings.

Any number is True, except 0.

Any list, tuple, set, and dictionary are True, except empty ones.

Example
The following will return True:

bool("abc")
bool(123)
bool(["apple", "cherry", "banana"])
Some Values are False
In fact, there are not many values that evaluate to False, except empty values,
such as (), [], {}, "", the number 0, and the value None. And of course the
value False evaluates to False.

Example
The following will return False:

bool(False)
bool(None)
bool(0)
bool("")
bool(())
bool([])
bool({})

One more value, or object in this case, evaluates to False, and that is if you
have an object that is made from a class with a __len__ function that
returns 0 or False:

Example
class myclass():
def __len__(self):
return 0

myobj = myclass()
print(bool(myobj))

Functions can Return a Boolean


You can create functions that returns a Boolean Value:

Example
Print the answer of a function:
def myFunction() :
return True

print(myFunction())

You can execute code based on the Boolean answer of a function:

Example
Print "YES!" if the function returns True, otherwise print "NO!":

def myFunction() :
return True

if myFunction():
print("YES!")
else:
print("NO!")
#output:Yes!

Note: Python also has many built-in functions that return a boolean value, like
the isinstance() function, which can be used to determine if an object is of a
certain data type:

Example
Check if an object is an integer or not:

x = 200
print(isinstance(x, int))
Lists are used to store multiple items in a single variable.

Lists are one of 4 built-in data types in Python used to store collections of data,
the other 3 are Tuple, Set, and Dictionary, all with different qualities and usage.

Lists are created using square brackets:

Example
Create a List:

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


print(thislist)
#Output: ['apple', 'banana', 'cherry']

List Items
List items are ordered, changeable, and allow duplicate values.

List items are indexed, the first item has index [0], the second item has
index [1] etc.

Ordered
When we say that lists are ordered, it means that the items have a defined
order, and that order will not change.

If you add new items to a list, the new items will be placed at the end of the
list.

Note: There are some list methods that will change the order, but in general:
the order of the items will not change.
Mutable
The list is changeable, meaning that we can change, add, and remove items in
a list after it has been created.

Allow Duplicates
Since lists are indexed, lists can have items with the same value:

Example
Lists allow duplicate values:

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


print(thislist)

List Length
To determine how many items a list has, use the len() function:

Example
Print the number of items in the list:

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


print(len(thislist))

List Items - Data Types


List items can be of any data type:

Example
String, int and boolean data types:
list1 = ["apple", "banana", "cherry"]
list2 = [1, 5, 7, 9, 3]
list3 = [True, False, False]

A list can contain different data types:

Example
A list with strings, integers and boolean values:

list1 = ["abc", 34, True, 40, "male"]

type()
From Python's perspective, lists are defined as objects with the data type 'list':

<class 'list'>

Example
What is the data type of a list?

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


print(type(mylist))

The list() Constructor


It is also possible to use the list() constructor when creating a new list.

Example
Using the list() constructor to make a List:

thislist = list(("apple", "banana", "cherry")) # note the double round-


brackets
print(thislist)
Python Collections (Arrays)
There are four collection data types in the Python programming language:

 List is a collection which is ordered and changeable. Allows duplicate


members.
 Tuple is a collection which is ordered and unchangeable. Allows duplicate
members.
 Set is a collection which is unordered, unchangeable*, and unindexed. No
duplicate members.
 Dictionary is a collection which is ordered** and changeable. No
duplicate members.

*Set items are unchangeable, but you can remove and/or add items whenever
you like.

**As of Python version 3.7, dictionaries are ordered. In Python 3.6 and earlier,
dictionaries are unordered.

When choosing a collection type, it is useful to understand the properties of that


type. Choosing the right type for a particular data set could mean retention of
meaning, and, it could mean an increase in efficiency or security

1.Access Items
List items are indexed and you can access them by referring to the index
number:

Example
Print the second item of the list:

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


print(thislist[1])
#output: banana
Note: The first item has index 0.

Negative Indexing
Negative indexing means start from the end

-1 refers to the last item, -2 refers to the second last item etc.

Example
Print the last item of the list:

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


print(thislist[-1])
#output: cherry

Range of Indexes
You can specify a range of indexes by specifying where to start and where to
end the range.

When specifying a range, the return value will be a new list with the specified
items.

Example
Return the third, fourth, and fifth item:

thislist =
["apple", "banana", "cherry", "orange", "kiwi", "melon", "mango"]
print(thislist[2:5])
#output: ['cherry', 'orange', 'kiwi']

Note: The search will start at index 2 (included) and end at index 5 (not
included).

Remember that the first item has index 0.


By leaving out the start value, the range will start at the first item:

Example
This example returns the items from the beginning to, but NOT including,
"kiwi":

thislist =
["apple", "banana", "cherry", "orange", "kiwi", "melon", "mango"]
print(thislist[:4])
#output: ['apple', 'banana', 'cherry', 'orange']

By leaving out the end value, the range will go on to the end of the list:

Example
This example returns the items from "cherry" to the end:

thislist =
["apple", "banana", "cherry", "orange", "kiwi", "melon", "mango"]
print(thislist[2:])
#output: ['cherry', 'orange', 'kiwi', 'melon', 'mango']

Range of Negative Indexes


Specify negative indexes if you want to start the search from the end of the list:

Example
This example returns the items from "orange" (-4) to, but NOT including
"mango" (-1):

thislist =
["apple", "banana", "cherry", "orange", "kiwi", "melon", "mango"]
print(thislist[-4:-1])
#output: ['orange', 'kiwi', 'melon']
Check if Item Exists
To determine if a specified item is present in a list use the in keyword:

Example
Check if "apple" is present in the list:

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


if "apple" in thislist:
print("Yes, 'apple' is in the fruits list")

2.Change and Insert Item Value


To change the value of a specific item, refer to the index number:

Example
Change the second item:

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


thislist[1] = "blackcurrant"
print(thislist)
#output: ['apple', 'blackcurrant', 'cherry']

Change a Range of Item Values


To change the value of items within a specific range, define a list with the new
values, and refer to the range of index numbers where you want to insert the
new values:

Example
Change the values "banana" and "cherry" with the values "blackcurrant" and
"watermelon":
thislist = ["apple", "banana", "cherry", "orange", "kiwi", "mango"]
thislist[1:3] = ["blackcurrant", "watermelon"]
print(thislist)
#output: ['apple', 'blackcurrant', 'watermelon', 'orange', 'kiwi',
'mango']

If you insert more items than you replace, the new items will be inserted where
you specified, and the remaining items will move accordingly:

Example
Change the second value by replacing it with two new values:

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


thislist[1:2] = ["blackcurrant", "watermelon"]
print(thislist)
#output: ['apple', 'blackcurrant', 'watermelon', 'cherry']

Note: The length of the list will change when the number of items inserted does
not match the number of items replaced.

If you insert less items than you replace, the new items will be inserted where
you specified, and the remaining items will move accordingly:

Example
Change the second and third value by replacing it with one value:

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


thislist[1:3] = ["watermelon"]
print(thislist)
#output: ['apple', 'watermelon']

Insert Items
To insert a new list item, without replacing any of the existing values, we can
use the insert() method.

The insert() method inserts an item at the specified index:

Example
Insert "watermelon" as the third item:

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


thislist.insert(2, "watermelon")
print(thislist)
#output: ['apple', 'banana', 'watermelon', 'cherry']

Append Items
To add an item to the end of the list, use the append() method:

Using the append() method to append an item:

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


thislist.append("orange")
print(thislist)

Insert Items
To insert a list item at a specified index, use the insert() method.

The insert() method inserts an item at the specified index:

Example
Insert an item as the second position:

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


thislist.insert(1, "orange")
print(thislist)
Note: As a result of the examples above, the lists will now contain 4 items.

Extend List
To append elements from another list to the current list, use
the extend() method.

Example
Add the elements of tropical to thislist:

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


tropical = ["mango", "pineapple", "papaya"]
thislist.extend(tropical)
print(thislist)

The elements will be added to the end of the list.

Add Any Iterable


The extend() method does not have to append lists, you can add any iterable
object (tuples, sets, dictionaries etc.).

Example
Add elements of a tuple to a list:

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


thistuple = ("kiwi", "orange")
thislist.extend(thistuple)
print(thislist)
3.Removing Items from a List in Python
Python provides several methods to remove items from a list. Each method has specific use cases
depending on whether you want to remove an item by value, by index, or clear the entire list.

1. Using the remove() Method

 Removes the first occurrence of a specified value from the list.


 Raises a ValueError if the value does not exist in the list.

Syntax:

list.remove(element)

Example:

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


fruits.remove("banana")
print(fruits) # Output: ["apple", "cherry", "banana"]

2. Using the pop() Method

 Removes an item at a specified index and returns it.


 If no index is specified, removes and returns the last item.
 Raises an IndexError if the index is out of range.

Syntax:

list.pop([index])

Example:

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


removed_item = fruits.pop(1)
print(fruits) # Output: ["apple", "cherry"]
print(removed_item) # Output: banana

3. Using the del Statement

 Deletes an item at a specific index or deletes a slice of items.


 Can also delete the entire list.

Syntax:
del list[index]

Example:

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


del fruits[1]
print(fruits) # Output: ["apple", "cherry"]

# Delete a slice
fruits = ["apple", "banana", "cherry", "date"]
del fruits[1:3]
print(fruits) # Output: ["apple", "date"]

4. Using the clear() Method

 Removes all items from the list, leaving it empty.

Syntax:

list.clear()

Example:

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


fruits.clear()
print(fruits) # Output: []

5. Using List Comprehension

 Create a new list by excluding specific items.

Example:

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


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

Comparison of Methods

Method Use Case Notes


remove() Remove an item by value Removes only the first occurrence.
pop()
Remove and return an item by Defaults to the last item if no index
index given.
del
Can delete multiple items or the entire
Remove by index or slice
list.
Method Use Case Notes
clear() Remove all items from the list Leaves the list empty.
List Remove multiple items by
Creates a new filtered list.
Comprehension condition

Key Points

1. Use remove() if you know the value to delete but not its index.
2. Use pop() or del to remove by index.
3. Use clear() to empty the entire list.
4. Use list comprehension for advanced filtering needs.

4.Looping Through Lists in Python


Python provides several ways to loop through a list, making it easy to process or manipulate its
elements. Below are the common methods for looping through lists:

1. Using a for Loop

 The for loop is the most commonly used method to iterate over each item in a list.

Syntax:

for item in list:


# Code to execute for each item

Example:

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


for fruit in fruits:
print(fruit)

Output:

apple
banana
cherry
2. Using for Loop with range()

 You can loop through the list using its index by combining the for loop with the range()
function.

Syntax:

for i in range(len(list)):
# Code to execute using list[i]

Example:

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


for i in range(len(fruits)):
print(fruits[i])

Output:

apple
banana
cherry

3. Using a while Loop

 A while loop can also be used to iterate through a list by maintaining an index variable.

Syntax:

index = 0
while index < len(list):
# Code to execute using list[index]
index += 1

Example:

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


index = 0
while index < len(fruits):
print(fruits[index])
index += 1

Output:

apple
banana
cherry
4. Using List Comprehension

 List comprehension is a concise way to loop through a list and perform operations on its
elements.

Syntax:

[operation for item in list]

Example:

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


upper_fruits = [fruit.upper() for fruit in fruits]
print(upper_fruits)

Output:

['APPLE', 'BANANA', 'CHERRY']

5. Using enumerate()

 The enumerate() function allows you to loop through a list and access both the index and the
value of each item.

Syntax:

for index, value in enumerate(list):


# Code to execute using index and value

Example:

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


for index, fruit in enumerate(fruits):
print(f"Index: {index}, Value: {fruit}")

Output:

Index: 0, Value: apple


Index: 1, Value: banana
Index: 2, Value: cherry

Key Points

 Use for loops for straightforward iteration.


 Combine for with range() for index-based iteration.
 Use while loops when more control over the index is needed.
 Leverage list comprehensions for concise looping with transformations.
 Use enumerate() to access both index and value during iteration.

5.List Comprehension in Python


List comprehension is a concise and elegant way to create and manipulate lists in Python. It is
often used to replace longer loops when performing simple operations.

Syntax of List Comprehension

The basic syntax of list comprehension is:

[expression for item in iterable if condition]

 expression: The operation or transformation to perform on each item.


 item: The variable representing each element in the iterable.
 iterable: The collection (like a list, range, or string) to loop through.
 condition (optional): A filter to include only specific items.

Examples of List Comprehension

1. Creating a List

 Example: Generate a list of squares for numbers from 1 to 5.

squares = [x**2 for x in range(1, 6)]


print(squares) # Output: [1, 4, 9, 16, 25]

2. Filtering a List

 Example: Include only even numbers from 1 to 10.

even_numbers = [x for x in range(1, 11) if x % 2 == 0]


print(even_numbers) # Output: [2, 4, 6, 8, 10]

3. Applying a Transformation

 Example: Convert a list of strings to uppercase.

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


uppercase_fruits = [fruit.upper() for fruit in fruits]
print(uppercase_fruits) # Output: ['APPLE', 'BANANA', 'CHERRY']
4. Nested List Comprehension

 Example: Create a 3x3 matrix.

matrix = [[j for j in range(3)] for i in range(3)]


print(matrix) # Output: [[0, 1, 2], [0, 1, 2], [0, 1, 2]]

List Comprehension vs Loops

List comprehension is more concise and readable compared to traditional loops. Here is an
example of both approaches:

Using a Loop:
squares = []
for x in range(1, 6):
squares.append(x**2)
print(squares) # Output: [1, 4, 9, 16, 25]

Using List Comprehension:


squares = [x**2 for x in range(1, 6)]
print(squares) # Output: [1, 4, 9, 16, 25]

Benefits of List Comprehension

1. Conciseness: Shorter and easier to write than loops.


2. Readability: More intuitive for simple list operations.
3. Performance: Generally faster than traditional loops for simple operations.

Key Points

 Use list comprehension for simple transformations and filtering.


 Avoid using it for complex operations as it can reduce readability.
 Combine with functions like range(), len(), or enumerate() for powerful list manipulations.

Would you like examples of more advanced list comprehension techniques or exercises?
6.Sorting Lists in Python
Sorting lists in Python is an essential operation for organizing data. Python provides multiple
ways to sort lists, both in ascending and descending order, and even with custom sorting criteria.

1. Using the sort() Method

 The sort() method sorts the list in place, modifying the original list.
 By default, it sorts in ascending order.

Syntax:

list.sort(key=None, reverse=False)

 key: (Optional) A function that serves as a key for sorting.


 reverse: (Optional) If True, sorts the list in descending order.

Example:

Ascending Order:

numbers = [5, 2, 9, 1, 5]
numbers.sort()
print(numbers) # Output: [1, 2, 5, 5, 9]

Descending Order:

numbers = [5, 2, 9, 1, 5]
numbers.sort(reverse=True)
print(numbers) # Output: [9, 5, 5, 2, 1]

Using a Custom Key:

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


fruits.sort(key=len)
print(fruits) # Output: ['apple', 'banana', 'cherry']

2. Using the sorted() Function

 The sorted() function returns a new sorted list, leaving the original list unchanged.
 By default, it sorts in ascending order.

Syntax:

sorted(iterable, key=None, reverse=False)


 iterable: The sequence to be sorted (e.g., list, tuple).
 key: (Optional) A function that serves as a key for sorting.
 reverse: (Optional) If True, sorts the iterable in descending order.

Example:

Ascending Order:

numbers = [5, 2, 9, 1, 5]
sorted_numbers = sorted(numbers)
print(sorted_numbers) # Output: [1, 2, 5, 5, 9]
print(numbers) # Output: [5, 2, 9, 1, 5]

Descending Order:

numbers = [5, 2, 9, 1, 5]
sorted_numbers = sorted(numbers, reverse=True)
print(sorted_numbers) # Output: [9, 5, 5, 2, 1]

Using a Custom Key:

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


sorted_fruits = sorted(fruits, key=len)
print(sorted_fruits) # Output: ['apple', 'banana', 'cherry']

3. Sorting Lists of Tuples or Dictionaries

You can sort lists containing complex data types like tuples or dictionaries by specifying a
custom key.

Sorting Tuples by Second Element:


pairs = [(1, 2), (3, 1), (5, 0)]
pairs.sort(key=lambda x: x[1])
print(pairs) # Output: [(5, 0), (3, 1), (1, 2)]

Sorting Dictionaries by Value:


students = {"Alice": 25, "Bob": 22, "Charlie": 30}
sorted_students = sorted(students.items(), key=lambda x: x[1])
print(sorted_students) # Output: [('Bob', 22), ('Alice', 25), ('Charlie',
30)]

Key Points

1. Use the sort() method to modify the list in place.


2. Use the sorted() function to create a new sorted list.
3. Use the key parameter for custom sorting criteria.
4. Use reverse=True for descending order.

Would you like to explore exercises or examples for practice?

7.Copy a List
You cannot copy a list simply by typing list2 = list1, because: list2 will only be
a reference to list1, and changes made in list1 will automatically also be made
in list2.

Use the copy() method


You can use the built-in List method copy() to copy a list.

ExampleGet your own Python Server


Make a copy of a list with the copy() method:

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


mylist = thislist.copy()
print(mylist)

Use the list() method


Another way to make a copy is to use the built-in method list().

Example
Make a copy of a list with the list() method:

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


mylist = list(thislist)
print(mylist)
Use the slice Operator
You can also make a copy of a list by using the : (slice) operator.

Example
Make a copy of a list with the : operator:

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


mylist = thislist[:]
print(mylist)

7.Join Two Lists


There are several ways to join, or concatenate, two or more lists in Python.

One of the easiest ways are by using the + operator.

Join two list:

list1 = ["a", "b", "c"]


list2 = [1, 2, 3]

list3 = list1 + list2


print(list3)

Another way to join two lists is by appending all the items from list2 into list1,
one by one:

Example
Append list2 into list1:

list1 = ["a", "b" , "c"]


list2 = [1, 2, 3]

for x in list2:
list1.append(x)

print(list1)
Or you can use the extend() method, where the purpose is to add elements from
one list to another list:

Example
Use the extend() method to add list2 at the end of list1:

list1 = ["a", "b" , "c"]


list2 = [1, 2, 3]

list1.extend(list2)
print(list1)

8.List Methods in Python


Python provides a wide range of built-in methods to manipulate and work with lists. These
methods allow you to perform common operations such as adding, removing, searching, and
modifying list elements.

Common List Methods

1. append()

Adds an element to the end of the list.

Syntax:

list.append(element)

Example:

fruits = ["apple", "banana"]


fruits.append("cherry")
print(fruits) # Output: ["apple", "banana", "cherry"]

2. extend()

Extends the list by adding elements from another iterable.

Syntax:
list.extend(iterable)

Example:

fruits = ["apple", "banana"]


fruits.extend(["cherry", "date"])
print(fruits) # Output: ["apple", "banana", "cherry", "date"]

3. insert()

Inserts an element at a specified index.

Syntax:

list.insert(index, element)

Example:

fruits = ["apple", "banana"]


fruits.insert(1, "cherry")
print(fruits) # Output: ["apple", "cherry", "banana"]

4. remove()

Removes the first occurrence of a specified value.

Syntax:

list.remove(element)

Example:

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


fruits.remove("banana")
print(fruits) # Output: ["apple", "cherry"]

5. pop()

Removes and returns the element at a specified index. If no index is provided, removes the last
element.

Syntax:

list.pop([index])
Example:

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


removed_item = fruits.pop(1)
print(fruits) # Output: ["apple", "cherry"]
print(removed_item) # Output: banana

6. clear()

Removes all elements from the list, leaving it empty.

Syntax:

list.clear()

Example:

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


fruits.clear()
print(fruits) # Output: []

7. index()

Returns the index of the first occurrence of a specified value.

Syntax:

list.index(element, [start], [end])

Example:

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


index = fruits.index("apple")
print(index) # Output: 0

8. count()

Returns the number of occurrences of a specified value.

Syntax:

list.count(element)

Example:
fruits = ["apple", "banana", "apple"]
count = fruits.count("apple")
print(count) # Output: 2

9. sort()

Sorts the list in ascending order by default. Use reverse=True for descending order.

Syntax:

list.sort(key=None, reverse=False)

Example:

numbers = [3, 1, 4, 1, 5]
numbers.sort()
print(numbers) # Output: [1, 1, 3, 4, 5]

10. reverse()

Reverses the order of elements in the list.

Syntax:

list.reverse()

Example:

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


fruits.reverse()
print(fruits) # Output: ["cherry", "banana", "apple"]

11. copy()

Creates a shallow copy of the list.

Syntax:

list.copy()

Example:

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


fruits_copy = fruits.copy()
print(fruits_copy) # Output: ["apple", "banana", "cherry"]
Summary Table:
Method Description

append() Adds an element to the end of the list.

extend() Extends the list by adding elements from another iterable.

insert() Inserts an element at a specified index.

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

pop() Removes and returns an element by index.

clear() Removes all elements from the list.

index() Returns the index of the first occurrence of a value.

count() Returns the number of occurrences of a value.

sort() Sorts the list in ascending or descending order.

reverse() Reverses the order of elements in the list.

copy() Creates a shallow copy of the list.

Key Points

 List methods modify lists efficiently and are easy to use.


 Use append() and extend() to add elements.
 Use remove(), pop(), or clear() to remove elements.
 Use sort() and reverse() to reorder elements.

Would you like to practice examples using these methods?

Allows
Data type Type Ordered Mutable
Duplicates
List Yes Yes Yes
Tuple Yes No Yes
Set No No No
Dictionary Yes Yes No
Tuple is a collection which is ordered and unchangeable. Allows duplicate
members.

Tuples are used to store multiple items in a single variable.

Tuple is one of 4 built-in data types in Python used to store collections of data,
the other 3 are List, Set, and Dictionary, all with different qualities and usage.

A tuple is a collection which is ordered and unchangeable.

Tuples are written with round brackets.

ExampleGet your own Python Server


Create a Tuple:

thistuple = ("apple", "banana", "cherry")


print(thistuple)

Tuple Items
Tuple items are ordered, unchangeable, and allow duplicate values.

Tuple items are indexed, the first item has index [0], the second item has
index [1] etc.

Ordered
When we say that tuples are ordered, it means that the items have a defined
order, and that order will not change.
Unchangeable
Tuples are unchangeable, meaning that we cannot change, add or remove items
after the tuple has been created.

Allow Duplicates
Since tuples are indexed, they can have items with the same value:

Example
Tuples allow duplicate values:

thistuple = ("apple", "banana", "cherry", "apple", "cherry")


print(thistuple)

Tuple Length
To determine how many items a tuple has, use the len() function:

Example
Print the number of items in the tuple:

thistuple = ("apple", "banana", "cherry")


print(len(thistuple))
Create Tuple With One Item
To create a tuple with only one item, you have to add a comma after the item,
otherwise Python will not recognize it as a tuple.

Example
One item tuple, remember the comma:

thistuple = ("apple",)
print(type(thistuple))

#NOT a tuple
thistuple = ("apple")
print(type(thistuple))

Tuple Items - Data Types


Tuple items can be of any data type:

Example
String, int and boolean data types:

tuple1 = ("apple", "banana", "cherry")


tuple2 = (1, 5, 7, 9, 3)
tuple3 = (True, False, False)

A tuple can contain different data types:

Example
A tuple with strings, integers and boolean values:

tuple1 = ("abc", 34, True, 40, "male")


type()
From Python's perspective, tuples are defined as objects with the data type
'tuple':

<class 'tuple'>

Example
What is the data type of a tuple?

mytuple = ("apple", "banana", "cherry")


print(type(mytuple))

The tuple() Constructor


It is also possible to use the tuple() constructor to make a tuple.

Example
Using the tuple() method to make a tuple:

thistuple = tuple(("apple", "banana", "cherry")) # note the double round-


brackets
print(thistuple)

Python Collections (Arrays)


There are four collection data types in the Python programming language:

 List is a collection which is ordered and changeable. Allows duplicate


members.
 Tuple is a collection which is ordered and unchangeable. Allows duplicate
members.
 Set is a collection which is unordered, unchangeable*, and unindexed. No
duplicate members.
 Dictionary is a collection which is ordered** and changeable. No
duplicate members.
*Set items are unchangeable, but you can remove and/or add items whenever
you like.

**As of Python version 3.7, dictionaries are ordered. In Python 3.6 and earlier,
dictionaries are unordered.

When choosing a collection type, it is useful to understand the properties of that


type. Choosing the right type for a particular data set could mean retention of
meaning, and, it could mean an increase in efficiency or security.

1.Access Tuple Items


You can access tuple items by referring to the index number, inside square
brackets:

Example
Print the second item in the tuple:

thistuple = ("apple", "banana", "cherry")


print(thistuple[1])

Note: The first item has index 0.

Negative Indexing
Negative indexing means start from the end.

-1 refers to the last item, -2 refers to the second last item etc.

Example
Print the last item of the tuple:

thistuple = ("apple", "banana", "cherry")


print(thistuple[-1])

Range of Indexes
You can specify a range of indexes by specifying where to start and where to
end the range.

When specifying a range, the return value will be a new tuple with the specified
items.

Example
Return the third, fourth, and fifth item:

thistuple =
("apple", "banana", "cherry", "orange", "kiwi", "melon", "mango")
print(thistuple[2:5])

Note: The search will start at index 2 (included) and end at index 5 (not
included).

Remember that the first item has index 0.

By leaving out the start value, the range will start at the first item:

Example
This example returns the items from the beginning to, but NOT included, "kiwi":

thistuple =
("apple", "banana", "cherry", "orange", "kiwi", "melon", "mango")
print(thistuple[:4])

By leaving out the end value, the range will go on to the end of the tuple:

Example
This example returns the items from "cherry" and to the end:
thistuple =
("apple", "banana", "cherry", "orange", "kiwi", "melon", "mango")
print(thistuple[2:])

Range of Negative Indexes


Specify negative indexes if you want to start the search from the end of the
tuple:

Example
This example returns the items from index -4 (included) to index -1 (excluded)

thistuple =
("apple", "banana", "cherry", "orange", "kiwi", "melon", "mango")
print(thistuple[-4:-1])

Check if Item Exists


To determine if a specified item is present in a tuple use the in keyword:

Example
Check if "apple" is present in the tuple:

thistuple = ("apple", "banana", "cherry")


if "apple" in thistuple:
print("Yes, 'apple' is in the fruits tuple")

2.Update Tuples
Tuples are unchangeable, meaning that you cannot change, add, or remove
items once the tuple is created.
But there are some workarounds.

Change Tuple Values


Once a tuple is created, you cannot change its values. Tuples
are unchangeable, or immutable as it also is called.

But there is a workaround. You can convert the tuple into a list, change the list,
and convert the list back into a tuple.

Example:
Convert the tuple into a list to be able to change it:

x = ("apple", "banana", "cherry")


y = list(x)
y[1] = "kiwi"
x = tuple(y)

print(x)

3.Add Items
Since tuples are immutable, they do not have a built-in append() method, but
there are other ways to add items to a tuple.

1. Convert into a list: Just like the workaround for changing a tuple, you can
convert it into a list, add your item(s), and convert it back into a tuple.

Example
Convert the tuple into a list, add "orange", and convert it back into a tuple:

thistuple = ("apple", "banana", "cherry")


y = list(thistuple)
y.append("orange")
thistuple = tuple(y)
2. Add tuple to a tuple. You are allowed to add tuples to tuples, so if you want
to add one item, (or many), create a new tuple with the item(s), and add it to
the existing tuple:

Example
Create a new tuple with the value "orange", and add that tuple:

thistuple = ("apple", "banana", "cherry")


y = ("orange",)
thistuple += y

print(thistuple)

Note: When creating a tuple with only one item, remember to include a comma
after the item, otherwise it will not be identified as a tuple.

4.Remove Items
Note: You cannot remove items in a tuple.

Tuples are unchangeable, so you cannot remove items from it, but you can
use the same workaround as we used for changing and adding tuple items:

Example
Convert the tuple into a list, remove "apple", and convert it back into a tuple:

thistuple = ("apple", "banana", "cherry")


y = list(thistuple)
y.remove("apple")
thistuple = tuple(y)

Or you can delete the tuple completely:

Example
The del keyword can delete the tuple completely:

thistuple = ("apple", "banana", "cherry")


del thistuple
print(thistuple) #this will raise an error because the tuple no longer
exists

5.Unpacking a Tuple
When we create a tuple, we normally assign values to it. This is called "packing"
a tuple:

Example:
Packing a tuple:

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

But, in Python, we are also allowed to extract the values back into variables.
This is called "unpacking":

Example
Unpacking a tuple:

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

(green, yellow, red) = fruits

print(green)
print(yellow)
print(red)

Note: The number of variables must match the number of values in the tuple, if
not, you must use an asterisk to collect the remaining values as a list.

Using Asterisk(*)
If the number of variables is less than the number of values, you can add
an * to the variable name and the values will be assigned to the variable as a
list:
Example
Assign the rest of the values as a list called "red":

fruits = ("apple", "banana", "cherry", "strawberry", "raspberry")

(green, yellow, *red) = fruits

print(green)
print(yellow)
print(red)

If the asterisk is added to another variable name than the last, Python will
assign values to the variable until the number of values left matches the
number of variables left.

Example
Add a list of values the "tropic" variable:

fruits = ("apple", "mango", "papaya", "pineapple", "cherry")

(green, *tropic, red) = fruits

print(green)
print(tropic)
print(red)

6.Loop Through a Tuple


You can loop through the tuple items by using a for loop.

Example:
Iterate through the items and print the values:

thistuple = ("apple", "banana", "cherry")


for x in thistuple:
print(x)

Learn more about for loops in our Python For Loops Chapter.
Loop Through the Index Numbers
You can also loop through the tuple items by referring to their index number.

Use the range() and len() functions to create a suitable iterable.

Example
Print all items by referring to their index number:

thistuple = ("apple", "banana", "cherry")


for i in range(len(thistuple)):
print(thistuple[i])

Using a While Loop


You can loop through the tuple items by using a while loop.

Use the len() function to determine the length of the tuple, then start at 0 and
loop your way through the tuple items by referring to their indexes.

Remember to increase the index by 1 after each iteration.

Example:
Print all items, using a while loop to go through all the index numbers:

thistuple = ("apple", "banana", "cherry")


i = 0
while i < len(thistuple):
print(thistuple[i])
i = i + 1
7.Join Two Tuples
To join two or more tuples you can use the + operator:

ExampleGet your own Python Server


Join two tuples:

tuple1 = ("a", "b" , "c")


tuple2 = (1, 2, 3)

tuple3 = tuple1 + tuple2


print(tuple3)

8.Multiply Tuples
If you want to multiply the content of a tuple a given number of times, you can
use the * operator:

Example
Multiply the fruits tuple by 2:

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


mytuple = fruits * 2

print(mytuple)

9.Tuple Methods in Python


Although tuples are immutable, Python provides a few built-in methods to work with tuples
efficiently. Here are the commonly used methods for tuples:

1. count()

Returns the number of times a specified value appears in the tuple.


Syntax:

tuple.count(value)

Example:

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


count = fruits.count("apple")
print(count) # Output: 2

2. index()

Returns the index of the first occurrence of a specified value. Raises a ValueError if the value is
not found.

Syntax:

tuple.index(value)

Example:

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


index = fruits.index("banana")
print(index) # Output: 1

Note:

 Since tuples are immutable, methods like append(), remove(), or pop() are not available for
tuples.
 Tuples are often used for storing fixed collections of data where immutability is required.
Sets are used to store multiple items in a single variable.

Set is one of 4 built-in data types in Python used to store collections of data,
the other 3 are List, Tuple, and Dictionary, all with different qualities and usage.

A set is a collection which is unordered, unchangeable*, and unindexed.

* Note: Set items are unchangeable, but you can remove items and add new
items.

Sets are written with curly brackets.

Example:
Create a Set:

thisset = {"apple", "banana", "cherry"}


print(thisset)

Note: Sets are unordered, so you cannot be sure in which order the items will
appear.

Key Characteristics of a Set:


Set items are unordered, unchangeable, and do not allow duplicate values.

a.Unordered
Unordered means that the items in a set do not have a defined order.

Set items can appear in a different order every time you use them, and cannot
be referred to by index or key.
b.Unchangeable/Immutable
Set items are unchangeable, meaning that we cannot change the items after
the set has been created.

Once a set is created, you cannot change its items, but you can remove items
and add new items.

3.Duplicates Not Allowed


Sets cannot have two items with the same value.

Example
Duplicate values will be ignored:

thisset = {"apple", "banana", "cherry", "apple"}

print(thisset)

Note: The values True and 1 are considered the same value in sets, and are
treated as duplicates:

Example
True and 1 is considered the same value:

thisset = {"apple", "banana", "cherry", True, 1, 2}

print(thisset)

Note: The values False and 0 are considered the same value in sets, and are
treated as duplicates:

Example
thisset = {"apple", "banana", "cherry", False, True, 0}

print(thisset)
4.Unindexed:
Set items cannot be accessed using indices.

Get the Length of a Set


To determine how many items a set has, use the len() function.

Example
Get the number of items in a set:

thisset = {"apple", "banana", "cherry"}

print(len(thisset))

Set Items - Data Types


Set items can be of any data type:

Example
String, int and boolean data types:

set1 = {"apple", "banana", "cherry"}


set2 = {1, 5, 7, 9, 3}
set3 = {True, False, False}

A set can contain different data types:

Example
A set with strings, integers and boolean values:

set1 = {"abc", 34, True, 40, "male"}


type()
From Python's perspective, sets are defined as objects with the data type 'set':

<class 'set'>

Example
What is the data type of a set?

myset = {"apple", "banana", "cherry"}


print(type(myset))

The set() Constructor


It is also possible to use the set() constructor to make a set.

Example
Using the set() constructor to make a set:

thisset = set(("apple", "banana", "cherry")) # note the double round-


brackets
print(thisset)

1.Access Items
You cannot access items in a set by referring to an index or a key.

But you can loop through the set items using a for loop, or ask if a specified
value is present in a set, by using the in keyword.
Example
Loop through the set, and print the values:

thisset = {"apple", "banana", "cherry"}

for x in thisset:
print(x)

Example
Check if "banana" is present in the set:

thisset = {"apple", "banana", "cherry"}

print("banana" in thisset)

Example
Check if "banana" is NOT present in the set:

thisset = {"apple", "banana", "cherry"}

print("banana" not in thisset)

2.Add Items
Once a set is created, you cannot change its items, but you can add new items.

To add one item to a set use the add() method.

ExampleGet your own Python Server


Add an item to a set, using the add() method:

thisset = {"apple", "banana", "cherry"}

thisset.add("orange")
print(thisset)
Add Sets
To add items from another set into the current set, use the update() method.

Example
Add elements from tropical into thisset:

thisset = {"apple", "banana", "cherry"}


tropical = {"pineapple", "mango", "papaya"}

thisset.update(tropical)

print(thisset)

Add Any Iterable


The object in the update() method does not have to be a set, it can be any
iterable object (tuples, lists, dictionaries etc.).

Example
Add elements of a list to at set:

thisset = {"apple", "banana", "cherry"}


mylist = ["kiwi", "orange"]

thisset.update(mylist)

print(thisset)

3.Remove Item
To remove an item in a set, use the remove(), or the discard() method.

Example
Remove "banana" by using the remove() method:
thisset = {"apple", "banana", "cherry"}

thisset.remove("banana")

print(thisset)

Note: If the item to remove does not exist, remove() will raise an error.

Example
Remove "banana" by using the discard() method:

thisset = {"apple", "banana", "cherry"}

thisset.discard("banana")

print(thisset)

Note: If the item to remove does not exist, discard() will NOT raise an error.

You can also use the pop() method to remove an item, but this method will
remove a random item, so you cannot be sure what item that gets removed.

The return value of the pop() method is the removed item.

Example
Remove a random item by using the pop() method:

thisset = {"apple", "banana", "cherry"}

x = thisset.pop()

print(x)

print(thisset)

Note: Sets are unordered, so when using the pop() method, you do not know
which item that gets removed.
The clear() method empties the set:

thisset = {"apple", "banana", "cherry"}

thisset.clear()

print(thisset)

Example
The del keyword will delete the set completely:

thisset = {"apple", "banana", "cherry"}

del thisset

print(thisset)

4.Loop Items
You can loop through the set items by using a for loop:

Example
Loop through the set, and print the values:

thisset = {"apple", "banana", "cherry"}

for x in thisset:
print(x)

5.Join Sets
There are several ways to join two or more sets in Python.

The union() and update() methods joins all items from both sets.

The intersection() method keeps ONLY the duplicates.


The difference() method keeps the items from the first set that are not in the
other set(s).

The symmetric_difference() method keeps all items EXCEPT the duplicates.

a.Union
The union() method returns a new set with all items from both sets.

Example:
Join set1 and set2 into a new set:

set1 = {"a", "b", "c"}


set2 = {1, 2, 3}
set3 = set1.union(set2)
print(set3)
#output: {1, 2, 3, 'b', 'a', 'c'}

You can use the | operator instead of the union() method, and you will get the
same result.

Example
Use | to join two sets:

set1 = {"a", "b", "c"}


set2 = {1, 2, 3}
set3 = set1 | set2
print(set3)
#output: {1, 2, 'a', 3, 'b', 'c'}

b.Join Multiple Sets


All the joining methods and operators can be used to join multiple sets.

When using a method, just add more sets in the parentheses, separated by
commas:
Example
Join multiple sets with the union() method:

set1 = {"a", "b", "c"}


set2 = {1, 2, 3}
set3 = {"John", "Elena"}
set4 = {"apple", "bananas", "cherry"}

myset = set1.union(set2, set3, set4)


print(myset)
#output: {1, 2, 3, 'bananas', 'a', 'apple', 'John', 'cherry', 'c',
'Elena', 'b'}

When using the | operator, separate the sets with more | operators:

Example
Use | to join two sets:

set1 = {"a", "b", "c"}


set2 = {1, 2, 3}
set3 = {"John", "Elena"}
set4 = {"apple", "bananas", "cherry"}

myset = set1 | set2 | set3 |set4


print(myset)

#output: {'Elena', 1, 2, 3, 'c', 'b', 'bananas', 'apple', 'a', 'cherry', 'John'}

c.Join a Set and a Tuple


The union() method allows you to join a set with other data types, like lists or
tuples.

The result will be a set.

Example
Join a set with a tuple:
x = {"a", "b", "c"}
y = (1, 2, 3)

z = x.union(y)
print(z)
#output: {'b', 1, 2, 3, 'c', 'a'}

Note: The | operator only allows you to join sets with sets, and not with other
data types like you can with the union() method.

d.Update
The update() method inserts all items from one set into another.

The update() changes the original set, and does not return a new set.

Example
The update() method inserts the items in set2 into set1:

set1 = {"a", "b" , "c"}


set2 = {1, 2, 3}

set1.update(set2)
print(set1)
#output: {1, 'c', 2, 3, 'a', 'b'}

Note: Both union() and update() will exclude any duplicate items.

e.Intersection
Keep ONLY the duplicates
The intersection() method will return a new set, that only contains the items
that are present in both sets.

Example
Join set1 and set2, but keep only the duplicates:

set1 = {"apple", "banana", "cherry"}


set2 = {"google", "microsoft", "apple"}

set3 = set1.intersection(set2)
print(set3)
#output: {'apple'}

You can use the & operator instead of the intersection() method, and you will
get the same result.

Example
Use & to join two sets:

set1 = {"apple", "banana", "cherry"}


set2 = {"google", "microsoft", "apple"}

set3 = set1 & set2


print(set3)
#output:{'apple'}

Note: The & operator only allows you to join sets with sets, and not with other
data types like you can with the intersection() method.

The intersection_update() method will also keep ONLY the duplicates, but it will
change the original set instead of returning a new set.

Example
Keep the items that exist in both set1, and set2:
set1 = {"apple", "banana", "cherry"}
set2 = {"google", "microsoft", "apple"}

set1.intersection_update(set2)

print(set1)
#output: {'apple'}

The values True and 1 are considered the same value. The same goes
for False and 0.

Example
Join sets that contains the values True, False, 1, and 0, and see what is
considered as duplicates:

set1 = {"apple", 1, "banana", 0, "cherry"}


set2 = {False, "google", 1, "apple", 2, True}

set3 = set1.intersection(set2)

print(set3)

#output: {False, 1, 'apple'}

f.Difference
The difference() method will return a new set that will contain only the items
from the first set that are not present in the other set.

Example
Keep all items from set1 that are not in set2:

set1 = {"apple", "banana", "cherry"}


set2 = {"google", "microsoft", "apple"}

set3 = set1.difference(set2)

print(set3)
#output: {'banana', 'cherry'}
You can use the - operator instead of the difference() method, and you will get
the same result.

Example
Use - to join two sets:

set1 = {"apple", "banana", "cherry"}


set2 = {"google", "microsoft", "apple"}

set3 = set1 - set2


print(set3)
#output: {'cherry', 'banana'}

Note: The - operator only allows you to join sets with sets, and not with other
data types like you can with the difference() method.

The difference_update() method will also keep the items from the first set that
are not in the other set, but it will change the original set instead of returning a
new set.

Example
Use the difference_update() method to keep the items that are not present in
both sets:

set1 = {"apple", "banana", "cherry"}


set2 = {"google", "microsoft", "apple"}

set1.difference_update(set2)

print(set1)
#output: {'banana', 'cherry'}
g.Symmetric Differences
The symmetric_difference() method will keep only the elements that are NOT
present in both sets.

Example
Keep the items that are not present in both sets:

set1 = {"apple", "banana", "cherry"}


set2 = {"google", "microsoft", "apple"}

set3 = set1.symmetric_difference(set2)

print(set3)
#output: {'banana', 'cherry', 'google', 'microsoft'}

You can use the ^ operator instead of the symmetric_difference() method, and you
will get the same result.

Example
Use ^ to join two sets:

set1 = {"apple", "banana", "cherry"}


set2 = {"google", "microsoft", "apple"}

set3 = set1 ^ set2


print(set3)
#output: {'google', 'cherry', 'banana', 'microsoft'}

Note: The ^ operator only allows you to join sets with sets, and not with other
data types like you can with the symmetric_difference() method.

The symmetric_difference_update() method will also keep all but the duplicates, but
it will change the original set instead of returning a new set.

Example
Use the symmetric_difference_update() method to keep the items that are not
present in both sets:

set1 = {"apple", "banana", "cherry"}


set2 = {"google", "microsoft", "apple"}

set1.symmetric_difference_update(set2)

print(set1)
#output: {'banana', 'microsoft', 'cherry', 'google'}

6.Common Set Methods in Python


Sets in Python come with several built-in methods that allow you to manipulate and analyze set
data efficiently. Here are some of the most commonly used set methods:

1. add()

Adds a single element to the set. If the element already exists, the set remains unchanged.

Syntax:

set.add(element)

Example:

my_set = {1, 2, 3}
my_set.add(4)
print(my_set) # Output: {1, 2, 3, 4}

2. remove()

Removes a specified element from the set. Raises a KeyError if the element is not found.

Syntax:

set.remove(element)

Example:
my_set = {1, 2, 3}
my_set.remove(2)
print(my_set) # Output: {1, 3}

3. discard()

Removes a specified element from the set but does NOT raise an error if the element is not
found.

Syntax:

set.discard(element)

Example:

my_set = {1, 2, 3}
my_set.discard(4) # No error
print(my_set) # Output: {1, 2, 3}

4. clear()

Removes all elements from the set, leaving it empty.

Syntax:

set.clear()

Example:

my_set = {1, 2, 3}
my_set.clear()
print(my_set) # Output: set()

5. union()

Combines all unique elements from two or more sets.

Syntax:

set.union(set1, set2, ...)

Example:

set1 = {1, 2, 3}
set2 = {3, 4, 5}
result = set1.union(set2)
print(result) # Output: {1, 2, 3, 4, 5}

6. intersection()

Returns a set containing only the elements that are common to all sets.

Syntax:

set.intersection(set1, set2, ...)

Example:

set1 = {1, 2, 3}
set2 = {2, 3, 4}
result = set1.intersection(set2)
print(result) # Output: {2, 3}

7. difference()

Returns a set containing elements that are in the first set but not in the others.

Syntax:

set.difference(set1, set2, ...)

Example:

set1 = {1, 2, 3}
set2 = {2, 3, 4}
result = set1.difference(set2)
print(result) # Output: {1}

8. symmetric_difference()

Returns a set containing elements that are in either of the sets, but not in both.

Syntax:

set.symmetric_difference(other_set)

Example:

set1 = {1, 2, 3}
set2 = {2, 3, 4}
result = set1.symmetric_difference(set2)
print(result) # Output: {1, 4}
Summary of Methods
Method Description

add() Adds a single element to the set.

remove() Removes a specified element (raises an error if not found).

discard() Removes a specified element (does not raise an error if not found).

clear() Removes all elements from the set.

union() Combines unique elements from multiple sets.

intersection() Finds common elements between sets.

difference() Finds elements present in one set but not in the others.

symmetric_difference() Finds elements in either of the sets, but not in both.


The frozenset is an immutable version of a set in Python. Unlike regular sets, the elements of a
frozenset cannot be modified after the frozenset is created. This makes frozensets hashable and
allows them to be used as keys in dictionaries or elements of other sets.

Characteristics of Frozen Sets

 Immutable: Once created, the elements of a frozenset cannot be changed (no add, remove, or
update operations).
 Hashable: Can be used as keys in dictionaries or as elements in other sets.
 Unordered: Like regular sets, frozensets do not maintain order.
 Duplicates not allowed: Duplicate elements are automatically removed.

Creating a Frozen Set

The frozenset() function is used to create a frozenset. You can pass any iterable (e.g., list,
tuple, set) to the frozenset() constructor.

Syntax:

frozenset(iterable)

Example:

# Creating a frozenset from a list


frozen_set = frozenset([1, 2, 3, 2])
print(frozen_set) # Output: frozenset({1, 2, 3})

Methods Available for Frozen Sets

Although frozensets are immutable, they support a few methods for analysis and operations.
These methods do not modify the frozenset but return new sets or values.

Method Description

copy() Returns a shallow copy of the frozenset.

union() Returns a new set containing all unique elements from both sets.
Method Description

intersection() Returns a set containing elements common to both sets.

difference() Returns a set containing elements in the frozenset but not in others.

symmetric_difference() Returns a set containing elements in either set but not in both.

issubset() Checks if the frozenset is a subset of another set.

issuperset() Checks if the frozenset is a superset of another set.

isdisjoint() Checks if the frozenset has no common elements with another set.

Example of Common Frozen Set Methods


# Define two frozensets
fs1 = frozenset([1, 2, 3])
fs2 = frozenset([3, 4, 5])

# Union
print(fs1.union(fs2)) # Output: frozenset({1, 2, 3, 4, 5})

# Intersection
print(fs1.intersection(fs2)) # Output: frozenset({3})

# Difference
print(fs1.difference(fs2)) # Output: frozenset({1, 2})

# Symmetric Difference
print(fs1.symmetric_difference(fs2)) # Output: frozenset({1, 2, 4, 5})

Key Points to Remember

1. Use frozensets when you need an immutable version of a set.


2. Frozensets are useful in scenarios where sets need to be used as keys in dictionaries.
3. Although immutable, frozensets support methods like union(), intersection(), and more,
which return new sets.

Would you like to explore more examples or practice with frozensets?


The range data type in Python is used to generate a sequence of numbers. It is commonly used
in loops and other scenarios where a sequence of numbers is required. The range object is
immutable, meaning its values cannot be changed after creation.

Characteristics of the range Data Type

 Immutable: Once created, the range object cannot be modified.


 Memory Efficient: The range object does not store all the numbers in memory. Instead, it
generates numbers on demand, making it efficient for large ranges.
 Sequence Type: Behaves like a sequence and supports operations such as indexing, slicing, and
iteration.

Syntax of range()

The range() function can take one, two, or three arguments:

range(stop)
range(start, stop)
range(start, stop, step)
Parameter Description

start (Optional) The starting value of the sequence. Defaults to 0.

stop The endpoint (exclusive) of the sequence.

step (Optional) The difference between each number in the sequence.

Examples of range()

1️⃣ Basic Usage


# Using range with one argument
for i in range(5):
print(i)
# Output: 0 1 2 3 4

2️⃣ Specifying Start and Stop


# Using range with two arguments
for i in range(2, 6):
print(i)
# Output: 2 3 4 5

3️⃣ Using a Step Value


# Using range with a step value
for i in range(1, 10, 2):
print(i)
# Output: 1 3 5 7 9

4️⃣ Negative Step Value


# Using a negative step value
for i in range(10, 0, -2):
print(i)
# Output: 10 8 6 4 2

5️⃣ Converting range to a List


# Converting a range to a list
numbers = list(range(5))
print(numbers)
# Output: [0, 1, 2, 3, 4]

Operations on range

The range object supports operations like:

 Indexing: Access elements using an index.


 r = range(1, 10, 2)
 print(r[2]) # Output: 5
 Slicing: Extract a subset of the range.
 r = range(1, 10)
 print(r[2:6]) # Output: range(3, 7)
 Iteration: Iterate through the range object using loops.

Key Points to Remember

1. The stop value is exclusive; it is not included in the range.


2. The step value can be positive or negative.
3. The range object is lazy, meaning it generates numbers as needed without storing them in
memory.
4. Convert range to a list if you need a materialized sequence of numbers.
Dictionaries are used to store data values in key:value pairs.

A dictionary is a collection which is ordered*, changeable and do not allow


duplicates.

As of Python version 3.7, dictionaries are ordered. In Python 3.6 and earlier,
dictionaries are unordered.

Dictionaries are written with curly brackets, and have keys and values:

Example
Create and print a dictionary:

thisdict = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
print(thisdict)

Dictionary Items
Dictionary items are ordered, changeable, and do not allow duplicates.
Dictionary items are presented in key:value pairs, and can be referred to by
using the key name.

Print the "brand" value of the dictionary:

thisdict = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
print(thisdict["brand"]) #output: Ford
Ordered or Unordered?
As of Python version 3.7, dictionaries are ordered. In Python 3.6 and earlier,
dictionaries are unordered.

When we say that dictionaries are ordered, it means that the items have a
defined order, and that order will not change.

Unordered means that the items do not have a defined order, you cannot refer
to an item by using an index.

Changeable
Dictionaries are changeable, meaning that we can change, add or remove items
after the dictionary has been created.

Duplicates Not Allowed


Dictionaries cannot have two items with the same key:

Example
Duplicate values will overwrite existing values:

thisdict = {
"brand": "Ford",
"model": "Mustang",
"year": 1964,
"year": 2020
}
print(thisdict)
Dictionary Length
To determine how many items a dictionary has, use the len() function:

Example
Print the number of items in the dictionary:

print(len(thisdict))

Dictionary Items - Data Types


The values in dictionary items can be of any data type:

Example
String, int, boolean, and list data types:

thisdict = {
"brand": "Ford",
"electric": False,
"year": 1964,
"colors": ["red", "white", "blue"]
}

type()
From Python's perspective, dictionaries are defined as objects with the data
type 'dict':

<class 'dict'>

Example
Print the data type of a dictionary:
thisdict = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
print(type(thisdict)) #output: <class 'dict'>

The dict() Constructor


It is also possible to use the dict() constructor to make a dictionary.

Example
Using the dict() method to make a dictionary:

thisdict = dict(name = "John", age = 36, country = "Norway")


print(thisdict)

#output: {'name': 'John', 'age': 36, 'country': 'Norway'}

1.Accessing Items
A dictionary in Python is a collection of key-value pairs. Accessing items in a dictionary can be
done using the key associated with a value. Python provides several ways to retrieve items from
a dictionary.

Accessing a Value Using a Key

 To access a specific value in a dictionary, use the key inside square brackets [].
 If the key does not exist, a KeyError is raised.

Example:
data = {"name": "Alice", "age": 25, "city": "New York"}
print(data["name"]) # Output: Alice
print(data["age"]) # Output: 25

Using the get() Method

 The get() method is a safer way to access dictionary values.


 It does not raise an error if the key does not exist; instead, it returns None (or a default value if
specified).

Syntax:
dictionary.get(key, default_value)

Example:
data = {"name": "Alice", "age": 25, "city": "New York"}
print(data.get("name")) # Output: Alice
print(data.get("country")) # Output: None
print(data.get("country", "USA")) # Output: USA

Accessing All Keys, Values, or Key-Value Pairs

Python provides methods to retrieve all keys, all values, or all key-value pairs from a dictionary.

1️⃣ Retrieving All Keys

 Use the keys() method to get a view object of all keys in the dictionary.

keys = data.keys()
print(keys) # Output: dict_keys(['name', 'age', 'city'])

2️⃣ Retrieving All Values

 Use the values() method to get a view object of all values in the dictionary.

values = data.values()
print(values) # Output: dict_values(['Alice', 25, 'New York'])

3️⃣ Retrieving All Key-Value Pairs

 Use the items() method to get a view object of all key-value pairs as tuples.

items = data.items()
print(items) # Output: dict_items([('name', 'Alice'), ('age', 25), ('city',
'New York')])
Iterating Through a Dictionary

You can loop through a dictionary to access its keys, values, or both.

Example:
data = {"name": "Alice", "age": 25, "city": "New York"}

# Looping through keys


for key in data:
print(key)

# Looping through values


for value in data.values():
print(value)

# Looping through key-value pairs


for key, value in data.items():
print(f"{key}: {value}")

Check if Key Exists


To determine if a specified key is present in a dictionary use the in keyword:

Example:
Check if "model" is present in the dictionary:

thisdict = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
if "model" in thisdict:
print("Yes, 'model' is one of the keys in the thisdict dictionary")
#output: Yes, 'model' is one of the keys in the thisdict dictionary

Key Points to Remember

1. Access dictionary values using square brackets [] or the get() method.


2. Use keys(), values(), and items() methods to retrieve all keys, values, or key-value pairs.
3. Use loops to iterate through the dictionary efficiently.
2.Changing Items in a Python Dictionary
A dictionary in Python allows you to modify its contents by changing the values associated with
existing keys or adding new key-value pairs.

Changing the Value of an Existing Key

 To change the value of a specific key, use square brackets [] and assign a new value.

Example:
data = {"name": "Alice", "age": 25, "city": "New York"}
data["age"] = 30
print(data)
# Output: {'name': 'Alice', 'age': 30, 'city': 'New York'}

Adding New Key-Value Pairs

 To add a new key-value pair, simply assign a value to a new key using square brackets [].

Example:
data = {"name": "Alice", "age": 25}
data["city"] = "New York"
print(data)
# Output: {'name': 'Alice', 'age': 25, 'city': 'New York'}

Updating Multiple Items Using the update() Method

 The update() method is used to update multiple key-value pairs at once. It can also add new
keys if they do not already exist.

Syntax:
dictionary.update(other_dictionary)

Example:
data = {"name": "Alice", "age": 25}
data.update({"age": 30, "city": "New York"})
print(data)
# Output: {'name': 'Alice', 'age': 30, 'city': 'New York'}
Key Points to Remember

1. Use square brackets [] to change the value of an existing key or add a new key-value pair.
2. Use the update() method to update multiple items or add new items efficiently.
3. Ensure the key you want to change or add is properly specified to avoid unintended
modifications.

Would you like to explore more advanced dictionary operations or practice some examples?

3.Adding and Removing Items


A dictionary in Python allows you to manage its contents by adding, updating, or removing key-
value pairs. This makes dictionaries versatile for data manipulation.

a.Adding Items to a Dictionary

Adding a Single Key-Value Pair

 To add a new key-value pair, simply assign a value to a new key using square brackets [].

Example:

data = {"name": "Alice", "age": 25}


data["city"] = "New York"
print(data)
# Output: {'name': 'Alice', 'age': 25, 'city': 'New York'}

Adding Multiple Key-Value Pairs

 Use the update() method to add multiple key-value pairs at once.

Syntax:

dictionary.update(other_dictionary)

Example:

data = {"name": "Alice", "age": 25}


data.update({"city": "New York", "country": "USA"})
print(data)
# Output: {'name': 'Alice', 'age': 25, 'city': 'New York', 'country': 'USA'}
b.Removing Items from a Dictionary

Removing a Specific Item

 Use the pop() method to remove an item by its key and retrieve its value.

Example:

data = {"name": "Alice", "age": 25, "city": "New York"}


age = data.pop("age")
print(data)
# Output: {'name': 'Alice', 'city': 'New York'}
print(age)
# Output: 25

Removing the Last Inserted Item

 Use the popitem() method to remove the last inserted key-value pair. This method is only
available in Python 3.7 and later.

Example:

data = {"name": "Alice", "age": 25, "city": "New York"}


last_item = data.popitem()
print(data)
# Output: {'name': 'Alice', 'age': 25'}
print(last_item)
# Output: ('city', 'New York')

Removing an Item Using del

 Use the del statement to delete an item by its key.

Example:

data = {"name": "Alice", "age": 25, "city": "New York"}


del data["city"]
print(data)
# Output: {'name': 'Alice', 'age': 25'}

Clearing the Entire Dictionary

 Use the clear() method to remove all items from the dictionary.

Example:

data = {"name": "Alice", "age": 25, "city": "New York"}


data.clear()
print(data)
# Output: {}

Deleting the Dictionary

 Use the del statement to delete the entire dictionary.

Example:

data = {"name": "Alice", "age": 25, "city": "New York"}


del data
# The `data` dictionary no longer exists.

Key Points to Remember

1. Use square brackets [] to add a single item or the update() method to add multiple items.
2. Use pop(), popitem(), or del to remove specific items.
3. Use clear() to empty a dictionary without deleting it.
4. Deleting the dictionary using del removes it entirely from memory.

Would you like to explore more dictionary operations or practice examples?

4.Loop Through a Dictionary


1. Looping Through Keys (Default): By default, when you loop through a dictionary, it
returns the keys.

python
CopyEdit
thisdict = {'name': 'John', 'age': 30, 'city': 'New York'}
for key in thisdict:
print(key)

Output:

CopyEdit
name
age
city

2. Looping Through Values: You can loop through the values of the dictionary by
accessing the value using the key.

python
CopyEdit
for key in thisdict:
print(thisdict[key])

Alternatively, you can use the values() method to directly get all values.

python
CopyEdit
for value in thisdict.values():
print(value)

Output:

sql
CopyEdit
John
30
New York

3. Looping Through Keys Using keys() Method: The keys() method returns the keys of
the dictionary, and you can loop through them.

python
CopyEdit
for key in thisdict.keys():
print(key)

4. Looping Through Both Keys and Values Using items() Method: The items()
method returns both the keys and the corresponding values. You can unpack them during
the loop.

python
CopyEdit
for key, value in thisdict.items():
print(key, value)

Output:

sql
CopyEdit
name John
age 30
city New York

These are the common ways to loop through a dictionary, providing flexibility depending on
whether you need just the keys, just the values, or both.
5.Copying a Dictionary in Python
1. Using the copy() Method: The copy() method creates a shallow copy of the dictionary.
This means that it creates a new dictionary with the same key-value pairs, but changes
made to the new dictionary won't affect the original one.

python
CopyEdit
thisdict = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
mydict = thisdict.copy()
print(mydict)

Output:

arduino
CopyEdit
{'brand': 'Ford', 'model': 'Mustang', 'year': 1964}

2. Using the dict() Function: The dict() function is another way to copy a dictionary. It
takes the original dictionary as an argument and creates a new dictionary with the same
contents.

python
CopyEdit
thisdict = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
mydict = dict(thisdict)
print(mydict)

Output:

arduino
CopyEdit
{'brand': 'Ford', 'model': 'Mustang', 'year': 1964}

Important Note:

 Shallow Copy: Both methods create a shallow copy of the dictionary. If the dictionary contains
nested objects (like lists or other dictionaries), changes to those objects will still affect both the
original and copied dictionaries. For a deep copy (which copies nested objects too), you can use
the copy module's deepcopy() method.
6.Nested Dictionaries in Python
A nested dictionary is a dictionary where some of the values are also dictionaries.

Example 1: Creating a Nested Dictionary

You can create a dictionary that contains other dictionaries. For example, creating a family
dictionary with each child as a sub-dictionary:

python
CopyEdit
myfamily = {
"child1": {
"name": "Emil",
"year": 2004
},
"child2": {
"name": "Tobias",
"year": 2007
},
"child3": {
"name": "Linus",
"year": 2011
}
}

Example 2: Creating Nested Dictionaries by Combining Other Dictionaries

You can also create individual dictionaries and then combine them into one dictionary:

python
CopyEdit
child1 = {
"name": "Emil",
"year": 2004
}
child2 = {
"name": "Tobias",
"year": 2007
}
child3 = {
"name": "Linus",
"year": 2011
}

myfamily = {
"child1": child1,
"child2": child2,
"child3": child3
}

Accessing Items in Nested Dictionaries


To access the items of a nested dictionary, you need to reference the keys of the outer and inner
dictionaries.

Example: Accessing a Nested Dictionary Item

To access the name of "child2":

python
CopyEdit
print(myfamily["child2"]["name"])

Output:

CopyEdit
Tobias

Looping Through Nested Dictionaries

You can loop through both the outer dictionary and its nested dictionaries using the items()
method.

Example: Looping Through the Keys and Values of Nested Dictionaries

python
CopyEdit
for key, obj in myfamily.items():
print(key)
for inner_key, inner_value in obj.items():
print(inner_key + ":", inner_value)

Output:

yaml
CopyEdit
child1
name: Emil
year: 2004
child2
name: Tobias
year: 2007
child3
name: Linus
year: 2011

Key Points:

 Accessing Values: Use multiple keys to access the nested values (e.g.,
myfamily["child2"]["name"]).
 Looping: Use items() to loop through both the outer and inner dictionaries.
 Nested Structure: Dictionaries within dictionaries allow for a hierarchical data structure, useful
for representing more complex relationships.

7.Python Dictionary Methods


A dictionary in Python is a collection of key-value pairs, where each key is unique. Python
dictionaries come with a variety of built-in methods that allow for efficient manipulation of the
dictionary data. Below are some commonly used dictionary methods, explained in a way suitable
for a college note:

1. clear()

Removes all items from the dictionary, making it empty.

Syntax:

python
CopyEdit
dict.clear()

Example:

python
CopyEdit
thisdict = {"name": "John", "age": 30}
thisdict.clear()
print(thisdict) # Output: {}

2. copy()

Returns a shallow copy of the dictionary. This means it copies the dictionary structure, but if the
dictionary contains nested objects, those objects are still referenced by both dictionaries.

Syntax:

python
CopyEdit
dict.copy()

Example:

python
CopyEdit
thisdict = {"name": "John", "age": 30}
newdict = thisdict.copy()
print(newdict) # Output: {'name': 'John', 'age': 30}

3. fromkeys()

Returns a new dictionary with keys from the provided sequence and values set to a specified
value (default is None).

Syntax:

python
CopyEdit
dict.fromkeys(sequence, value)

Example:

python
CopyEdit
keys = ("a", "b", "c")
newdict = dict.fromkeys(keys, 0)
print(newdict) # Output: {'a': 0, 'b': 0, 'c': 0}

4. get()

Returns the value for the specified key if the key exists in the dictionary. If the key does not
exist, it returns None (or a specified default value if provided).

Syntax:

python
CopyEdit
dict.get(key, default_value)

Example:

python
CopyEdit
thisdict = {"name": "John", "age": 30}
print(thisdict.get("name")) # Output: John
print(thisdict.get("address", "Not Found")) # Output: Not Found

5. items()

Returns a view object that displays a list of a dictionary's key-value tuple pairs.
Syntax:

python
CopyEdit
dict.items()

Example:

python
CopyEdit
thisdict = {"name": "John", "age": 30}
print(thisdict.items()) # Output: dict_items([('name', 'John'), ('age',
30)])

6. keys()

Returns a view object that displays all the keys in the dictionary.

Syntax:

python
CopyEdit
dict.keys()

Example:

python
CopyEdit
thisdict = {"name": "John", "age": 30}
print(thisdict.keys()) # Output: dict_keys(['name', 'age'])

7. pop()

Removes the specified key and returns the corresponding value. If the key does not exist, it raises
a KeyError. Optionally, a default value can be provided to return if the key is not found.

Syntax:

python
CopyEdit
dict.pop(key, default_value)

Example:

python
CopyEdit
thisdict = {"name": "John", "age": 30}
removed_value = thisdict.pop("age")
print(removed_value) # Output: 30
print(thisdict) # Output: {'name': 'John'}

8. popitem()

Removes and returns the last inserted key-value pair as a tuple. This method is useful when
working with the dictionary in a LIFO (Last In, First Out) manner.

Syntax:

python
CopyEdit
dict.popitem()

Example:

python
CopyEdit
thisdict = {"name": "John", "age": 30}
last_item = thisdict.popitem()
print(last_item) # Output: ('age', 30)
print(thisdict) # Output: {'name': 'John'}

9. setdefault()

Returns the value of a key if it exists. If the key does not exist, it inserts the key with a specified
default value and returns that value.

Syntax:

python
CopyEdit
dict.setdefault(key, default_value)

Example:

python
CopyEdit
thisdict = {"name": "John", "age": 30}
print(thisdict.setdefault("address", "Unknown")) # Output: Unknown
print(thisdict) # Output: {'name': 'John', 'age': 30, 'address': 'Unknown'}

10. update()

Updates the dictionary with the specified key-value pairs. If the key exists, it updates the value.
If the key doesn't exist, it adds the key-value pair.
Syntax:

python
CopyEdit
dict.update(iterable)

Example:

python
CopyEdit
thisdict = {"name": "John", "age": 30}
thisdict.update({"age": 35, "city": "New York"})
print(thisdict) # Output: {'name': 'John', 'age': 35, 'city': 'New York'}

11. values()

Returns a view object that displays all the values in the dictionary.

Syntax:

python
CopyEdit
dict.values()

Example:

python
CopyEdit
thisdict = {"name": "John", "age": 30}
print(thisdict.values()) # Output: dict_values(['John', 30])

Summary of Methods:

 clear(): Clears all items in the dictionary.


 copy(): Returns a shallow copy of the dictionary.
 fromkeys(): Creates a new dictionary with specified keys and values.
 get(): Retrieves the value for a specified key (with optional default).
 items(): Returns all key-value pairs as tuples.
 keys(): Returns all keys in the dictionary.
 pop(): Removes a specified key and returns its value.
 popitem(): Removes and returns the last inserted key-value pair.
 setdefault(): Returns the value of a key or inserts a default value if the key doesn't exist.
 update(): Updates the dictionary with new key-value pairs.
 values(): Returns all values in the dictionary.
Python Collections (Arrays)
There are four collection data types in the Python programming language:

 List is a collection which is ordered and changeable. Allows duplicate


members.
 Tuple is a collection which is ordered and unchangeable. Allows duplicate
members.
 Set is a collection which is unordered, unchangeable*, and unindexed. No
duplicate members.
 Dictionary is a collection which is ordered** and changeable. No
duplicate members.

Iterator in Python:
An iterator in Python is an object that allows you to traverse through all the elements in a
collection (such as a list, tuple, or string) one at a time. It adheres to the iterator protocol, which
consists of two main methods:

1. __iter__(): This method is used to initialize the iterator and return the iterator object itself.
2. __next__(): This method returns the next item in the sequence. If there are no more items
left, it raises a StopIteration exception to signal the end of the iteration.

Creating an Iterator

To create an iterator in Python, you need two components:

1. An iterable: This is an object that can return an iterator (e.g., a list, tuple, or string).
2. An iterator: An iterator is an object that implements the __iter__() and __next__()
methods.

Example: Custom Iterator Class

Here's an example of creating a custom iterator:

python
CopyEdit
class MyIterator:
def __init__(self, start, end):
self.current = start
self.end = end
def __iter__(self):
return self # The object itself is the iterator

def __next__(self):
if self.current > self.end:
raise StopIteration # Signals the end of iteration
self.current += 1
return self.current - 1

# Using the iterator


my_iter = MyIterator(1, 5)
for number in my_iter:
print(number)

Output:

CopyEdit
1
2
3
4
5

Built-in Iterators in Python

Python has many built-in iterable objects, such as:

 Lists
 Tuples
 Strings
 Dictionaries (iterate over keys or values)
 Sets

These iterables can be converted into iterators by using the iter() function.

Example of Using an Iterator with Built-in Iterables:


python
CopyEdit
my_list = [10, 20, 30, 40]

# Get the iterator from the list


iter_list = iter(my_list)

# Use next() to access items one by one


print(next(iter_list)) # 10
print(next(iter_list)) # 20
print(next(iter_list)) # 30
print(next(iter_list)) # 40

If you try to call next() again when there are no more items, it will raise a StopIteration
exception.
The for Loop and Iterators

Python's for loop automatically uses the __iter__() and __next__() methods behind the
scenes to iterate over an iterable object, making it easy to work with iterators.

Example with a for loop:

python
CopyEdit
my_list = [10, 20, 30, 40]

# Directly iterating using for loop


for item in my_list:
print(item)

Output:

CopyEdit
10
20
30
40

Why Use Iterators?

1. Memory Efficiency: Iterators allow you to iterate over large data sets or streams without
loading everything into memory at once.
2. Lazy Evaluation: Iterators generate values only when needed, which can improve performance
when dealing with large datasets.
3. Custom Behavior: You can create your own iterators to control how elements are accessed,
filtered, or transformed.

Conclusion

An iterator in Python provides a flexible way to access elements of a collection one at a time,
and it is a powerful tool for handling large datasets efficiently. You can either use Python's built-
in iterables or create custom iterators for your own needs.

In Python, binary data refers to data that is represented in binary form (as a sequence of 0s and
1s), which can be used for various purposes such as storing and processing non-text data like
images, files, and other types of data that are not human-readable. Python provides several ways
to work with binary data, such as using built-in types, encoding and decoding methods, and
specialized modules.

1. bytes Type 🧑💻
The bytes type in Python is used to represent immutable binary data (data that cannot be
changed after creation). This type is typically used for working with raw binary data, such as
reading or writing binary files.

Syntax:

python
CopyEdit
b = bytes([65, 66, 67]) # Creates a bytes object from a list of integers

Example:

python
CopyEdit
b = bytes([65, 66, 67])
print(b) # Output: b'ABC'

In this example, 65, 66, and 67 are the ASCII values for the characters A, B, and C. The bytes
object represents this as binary data.

2. bytearray Type 🔄
The bytearray type is similar to bytes, but it is mutable (can be modified). This is useful when
you need to modify binary data during the execution of your program.

Syntax:

python
CopyEdit
b = bytearray([65, 66, 67]) # Creates a bytearray object from a list of
integers

Example:

python
CopyEdit
b = bytearray([65, 66, 67])
print(b) # Output: bytearray(b'ABC')
b[0] = 90 # Change the first byte to 90 (ASCII 'Z')
print(b) # Output: bytearray(b'ZBC')

In this example, bytearray allows us to modify the content after creation, unlike bytes.

3. Binary Literals (Prefix 0b) 🔢


You can represent binary numbers directly using binary literals by prefixing them with 0b or 0B.

Syntax:

python
CopyEdit
bin_value = 0b1101 # Binary literal representing 13

Example:

python
CopyEdit
bin_value = 0b1101
print(bin_value) # Output: 13 (decimal representation)

In this example, 0b1101 is a binary literal that is equal to 13 in decimal.

4. Converting Between Binary and Other Data Types


Python allows easy conversion between binary and other data types, such as integers and strings.

 Convert Integer to Binary: Use the built-in bin() function to convert an integer to a
binary string.

python
CopyEdit
x = 13
binary_str = bin(x) # Output: '0b1101'

 Convert Binary String to Integer: You can use int() with base 2 to convert a binary
string back to an integer.

python
CopyEdit
binary_str = '0b1101'
x = int(binary_str, 2) # Output: 13
 Convert String to Binary Data: You can convert a string into a binary representation
using the encode() method.

python
CopyEdit
string = "hello"
binary_data = string.encode('utf-8') # Converts string to binary data
using UTF-8 encoding
print(binary_data) # Output: b'hello'

5. Working with Binary Files 📂


You can read and write binary files using the open() function in binary mode. Binary files store
data in raw binary form and are useful for dealing with images, audio files, videos, or any other
file formats that are not text-based.

Syntax:

 Reading in binary mode:

python
CopyEdit
with open('file.bin', 'rb') as f:
binary_data = f.read()

 Writing in binary mode:

python
CopyEdit
with open('file.bin', 'wb') as f:
f.write(binary_data)

Example: Reading a Binary File

python
CopyEdit
with open('image.jpg', 'rb') as file:
binary_data = file.read()
print(binary_data[:10]) # Output first 10 bytes of the binary file

In this example, we open a file (image.jpg) in binary mode ('rb') and read its contents.

Summary of Binary Data Types:

 bytes: Immutable binary data type, useful for storing binary data.
 bytearray: Mutable binary data type, useful when you need to modify the binary data.
 Binary literals (0b): Allows direct representation of binary numbers.
 Conversion functions: bin() for converting integers to binary, int() for converting
binary strings to integers, and encode() for converting strings to binary data.
 Binary files: Use open() in binary mode ('rb' and 'wb') for reading and writing binary
files.

Python's support for binary data types allows you to efficiently work with non-textual data, such
as images, audio, and video files, and to process raw data in a variety of applications.

In Python, None is a special constant that represents the absence of a value or null value. It is
often used to indicate that a variable has no value, or that a function does not explicitly return a
value.

1. What is None?
 None is a singleton object in Python. This means that there is only one instance of None
in a Python program. It is often used as a default value for variables, function parameters,
or return values.
 It is of type NoneType, which is a built-in type in Python.

Syntax:

python
CopyEdit
x = None

Example:

python
CopyEdit
x = None
print(x) # Output: None
In this example, x is assigned the value None, meaning it doesn't have any value or data
associated with it.

2. Common Uses of None 🔄


a. Default Function Return Value 📤

When a function does not explicitly return a value, it implicitly returns None. This is a way of
indicating that no meaningful value is returned.

python
CopyEdit
def my_function():
print("Hello")

result = my_function()
print(result) # Output: None

In this example, my_function() prints "Hello" but does not return anything, so result is
assigned None.

b. Default Function Parameters 📋

None is often used as a default value for function parameters to indicate that no argument has
been passed for that parameter. It can then be checked within the function to set a value or
perform an action.

python
CopyEdit
def greet(name=None):
if name is None:
print("Hello, Stranger!")
else:
print(f"Hello, {name}!")

greet() # Output: Hello, Stranger!


greet("Alice") # Output: Hello, Alice!

In this example, if no argument is passed to the name parameter, it defaults to None and the
function prints "Hello, Stranger!".

c. Representing Missing or Null Data 📊


In situations where data might be missing or unknown, None can be used to represent this
absence.

python
CopyEdit
student = {"name": "John", "age": None}
print(student) # Output: {'name': 'John', 'age': None}

Here, None is used to represent the missing value for the student's age.

3. Comparing None 🔎
 Noneis a unique value and should be compared using is rather than == for identity
comparison.

Correct Comparison:

python
CopyEdit
x = None
if x is None:
print("x is None") # Output: x is None

Incorrect Comparison (should not use == with None):

python
CopyEdit
x = None
if x == None: # This works but is not the recommended way
print("x is None") # Output: x is None

The is operator checks for identity, meaning that x is None checks if x is the same object as
None, while == checks for equality (although they happen to behave similarly when comparing to
None).

4. None and Boolean Context ⚖️


In Python, None is considered False in a boolean context. It is equivalent to False when
evaluated in conditions.

Example:

python
CopyEdit
x = None

if not x:
print("x is None or False") # Output: x is None or False

In this example, since None is falsy, the if condition evaluates to True, and the message is
printed.

5. Common Operations with None ⚙️


 Assigning None: You can assign None to a variable to indicate the absence of a value.

python
CopyEdit
x = None

 Using None as a placeholder: It is used in lists, dictionaries, or classes to indicate


missing or undefined values.

python
CopyEdit
my_dict = {"key1": 10, "key2": None}

Summary of None Data Type:

 None represents the absence of a value or null value in Python.


 It is of type NoneType.
 Common uses of None include:
o Default return value for functions that do not explicitly return a value.
o Default value for function parameters.
o Representing missing or null data in variables, lists, or dictionaries.
 Use the is operator to compare None instead of == for identity comparison.
 None is falsy in boolean contexts (equivalent to False).

Type casting (or type conversion) in Python refers to converting one data type into another. It
allows you to manipulate data in different formats depending on the needs of your program.

Python provides two types of type casting:


1. Implicit Type Casting
2. Explicit Type Casting

1. Implicit Type Casting


In implicit type casting, Python automatically converts a value from one data type to another
without any user intervention. This usually happens when mixing different types in an operation,
and Python converts them into a common type to avoid errors.

Example:

python
CopyEdit
num_int = 5 # Integer
num_float = 2.5 # Float

# Python automatically converts 'num_int' to float


result = num_int + num_float

print(result) # Output: 7.5


print(type(result)) # Output: <class 'float'>

In this case, Python promotes the integer (int) to a float (float) because the operation involves
both data types.

2. Explicit Type Casting


In explicit type casting, the programmer manually converts one data type into another using
Python's built-in functions. This is also called type coercion.

Common Functions for Type Casting

Function Description

int() Converts to an integer. Removes decimal parts or converts strings to integers.

float() Converts to a floating-point number.

str() Converts to a string.

bool() Converts to a boolean.

list() Converts to a list.


Function Description

tuple() Converts to a tuple.

set() Converts to a set.

dict() Converts to a dictionary (from key-value pairs).

Examples of Explicit Type Casting:


1. Integer to Float:

python
CopyEdit
num = 10
print(float(num)) # Output: 10.0

2. Float to Integer:

python
CopyEdit
num = 10.8
print(int(num)) # Output: 10

3. String to Integer:

python
CopyEdit
num_str = "123"
print(int(num_str)) # Output: 123

4. String to Float:

python
CopyEdit
num_str = "123.45"
print(float(num_str)) # Output: 123.45

5. Integer to String:

python
CopyEdit
num = 456
print(str(num)) # Output: "456"

6. List to Set:

python
CopyEdit
my_list = [1, 2, 2, 3]
print(set(my_list)) # Output: {1, 2, 3}

7. Tuple to List:

python
CopyEdit
my_tuple = (1, 2, 3)
print(list(my_tuple)) # Output: [1, 2, 3]

8. Boolean to Integer:

python
CopyEdit
print(int(True)) # Output: 1
print(int(False)) # Output: 0

Important Notes on Explicit Casting

1. Invalid Conversions Cause Errors:


o You cannot directly convert incompatible types. For example:

python
CopyEdit
num_str = "abc"
print(int(num_str)) # Raises ValueError

2. Loss of Data:
o Converting a float to an integer truncates the decimal part:

python
CopyEdit
num = 5.9
print(int(num)) # Output: 5

3. Strings Must Be Compatible:


o Only strings representing valid numbers can be converted to numeric types:

python
CopyEdit
print(float("123.45")) # Valid
print(int("123a")) # Invalid (raises ValueError)

Practical Use Cases of Type Casting


1. Taking Numeric Input from Users: User inputs are always strings, so they need to be
converted to integers or floats for mathematical operations.
python
CopyEdit
num1 = int(input("Enter first number: "))
num2 = float(input("Enter second number: "))
print("Sum:", num1 + num2)

2. Handling Data Types in Arithmetic: Converting values to a common type for


operations:

python
CopyEdit
result = int(5.8) + float(10)
print(result) # Output: 15.0

3. Working with Collections: Converting between lists, tuples, and sets:

python
CopyEdit
my_tuple = (1, 2, 3)
my_list = list(my_tuple)
print(my_list) # Output: [1, 2, 3]

4. Boolean Logic: Converting boolean values to integers for computations:

python
CopyEdit
print(True + True) # Output: 2
print(False * 10) # Output: 0

Conclusion

Type casting in Python provides flexibility to manipulate data between different types based on
the program's requirements. While implicit type casting simplifies operations by automatically
promoting data types, explicit type casting gives you precise control over how data should be
transformed. Always ensure conversions are valid to avoid runtime errors!
A generator in Python is a special type of iterable that allows you to create an iterator in a more
efficient and concise way. Instead of returning all the values at once (like a list), a generator
produces values on the fly, one at a time, and only when requested.

Generators are defined using a normal function with the yield keyword instead of return.

Key Features of Generators

1. Lazy Evaluation: Generators produce values only when they are requested, making them
memory-efficient.
2. State Retention: Generators remember their state between iterations, so they can resume
execution right after the last yield statement.
3. Iterables: Generators are inherently iterable, meaning you can use them in loops or with
functions like next().

How to Create a Generator

1. Using a Function with yield

A generator function is a normal Python function but uses the yield keyword instead of return
to produce a series of values.

Example:

python
CopyEdit
def simple_generator():
yield 1
yield 2
yield 3

gen = simple_generator() # Creates the generator object

print(next(gen)) # Output: 1
print(next(gen)) # Output: 2
print(next(gen)) # Output: 3
# print(next(gen)) # Raises StopIteration (end of generator)

 Each time yield is encountered, the function pauses and produces the value.
 When next() is called again, the function resumes where it left off.
2. Using Generator Expressions

A generator expression is a concise way to create a generator, similar to list comprehensions but
with parentheses instead of square brackets.

Example:

python
CopyEdit
gen_exp = (x ** 2 for x in range(5))

for num in gen_exp:


print(num, end=" ") # Output: 0 1 4 9 16

Key Differences Between yield and return

yield return

Produces a value and pauses the function. Exits the function and sends back a value.

Can be called multiple times (resumes execution). Terminates the function completely.

Used in generator functions to create iterators. Used in normal functions.

Advantages of Generators

1. Memory Efficiency: Generators do not store all the values in memory; they generate
values on demand. This is especially useful for processing large datasets.

python
CopyEdit
def large_numbers():
for i in range(1_000_000):
yield i

gen = large_numbers() # Creates generator object


print(next(gen)) # Output: 1

2. Simpler Code: Generators provide a cleaner way to write iterators without manually
implementing __iter__() and __next__() methods.
3. Infinite Sequences: Generators can represent infinite sequences because they generate
values lazily.

python
CopyEdit
def infinite_numbers():
num = 0
while True:
yield num
num += 1

gen = infinite_numbers()
print(next(gen)) # Output: 0
print(next(gen)) # Output: 1

Generator Methods

1. next()

Used to retrieve the next value from the generator.

Example:

python
CopyEdit
def generator():
yield "A"
yield "B"

gen = generator()
print(next(gen)) # Output: A
print(next(gen)) # Output: B

2. send()

Used to send a value into the generator and resume its execution.

Example:

python
CopyEdit
def generator_with_send():
value = yield "Start"
yield f"Received: {value}"

gen = generator_with_send()
print(next(gen)) # Output: Start
print(gen.send("Hello")) # Output: Received: Hello

3. close()

Stops the generator by raising a GeneratorExit exception.

Example:
python
CopyEdit
def my_gen():
yield 1
yield 2

gen = my_gen()
print(next(gen)) # Output: 1
gen.close()
# print(next(gen)) # Raises StopIteration

Real-World Applications of Generators

1. Processing Large Files: Instead of loading an entire file into memory, you can process it
line by line with a generator.

python
CopyEdit
def read_large_file(file_path):
with open(file_path) as file:
for line in file:
yield line.strip()

for line in read_large_file("large_file.txt"):


print(line)

2. Stream Processing: Generators are ideal for handling streaming data, such as reading
data from an API or processing live logs.
3. Pipeline Processing: Generators allow you to chain multiple transformations efficiently.

python
CopyEdit
def generator1():
for i in range(5):
yield i

def generator2(gen):
for value in gen:
yield value ** 2

pipeline = generator2(generator1())
for val in pipeline:
print(val) # Output: 0 1 4 9 16

Conclusion

Generators are a powerful feature in Python that enable lazy evaluation, memory efficiency,
and cleaner code for creating iterators. By using the yield keyword or generator expressions,
you can process large datasets, create infinite sequences, and build efficient data pipelines with
ease.
In Python, keywords are reserved words that have special meaning and purpose within the
language. These words are part of Python's syntax and cannot be used as identifiers (names for
variables, functions, or classes). They are used to define the structure and logic of Python
programs.

Characteristics of Python Keywords


1. Case-sensitive: Python keywords are always written in lowercase (except for True,
False, and None).
2. Fixed meanings: You cannot use them for any purpose other than what they are intended
for.
3. Reserved words: They cannot be used as variable or function names.

List of Python Keywords


Below is the complete list of Python keywords (as of Python 3.10+):

Keyword Description
False Boolean value representing falsehood.
True Boolean value representing truth.
None Represents the absence of a value or a null value.
and Logical AND operator.
or Logical OR operator.
not Logical NOT operator.
if Conditional statement.
elif Else-if conditional statement.
else Default block of code if the if condition is false.
while Looping statement (runs as long as a condition is true).
for Looping statement (iterates over sequences).
break Terminates the nearest enclosing loop.
continue Skips the current iteration of the loop and continues to the next.
def Used to define a function.
return Exits a function and optionally returns a value.
Keyword Description
yield Used in generators to return a value and pause execution.
class Defines a class.
pass Placeholder statement that does nothing.
import Imports a module.
from Used with import to import specific parts of a module.
as Used to give an alias to a module or object.
try Defines a block of code to test for exceptions.
except Defines a block of code to handle exceptions.
finally Defines a block of code to execute no matter what.
raise Raises an exception.
assert Debugging tool to test a condition.
del Deletes objects or variables.
with Used to simplify exception handling by wrapping resources.
lambda Defines anonymous functions (lambda expressions).
global Declares a global variable inside a function.
nonlocal Declares a variable as nonlocal in nested functions.
in Membership operator (checks if an element exists in a sequence).
is Identity operator (checks if two objects are the same).
None Represents the absence of a value or null value.
async Declares an asynchronous function or task.
await Used to pause and resume asynchronous functions.

Examples of Python Keywords in Action


1. if, elif, and else

python
CopyEdit
x = 10

if x > 5:
print("x is greater than 5")
elif x == 5:
print("x is equal to 5")
else:
print("x is less than 5")

2. while and break

python
CopyEdit
i = 0

while i < 5:
print(i)
if i == 3:
break # Exit the loop when i equals 3
i += 1

3. def and return

python
CopyEdit
def add_numbers(a, b):
return a + b

result = add_numbers(3, 5)
print(result) # Output: 8

4. try, except, and finally

python
CopyEdit
try:
num = int(input("Enter a number: "))
print(10 / num)
except ValueError:
print("Invalid input! Please enter a number.")
except ZeroDivisionError:
print("Division by zero is not allowed.")
finally:
print("Execution complete.")

5. lambda

python
CopyEdit
square = lambda x: x ** 2
print(square(4)) # Output: 16

How to View Keywords in Python


You can use the keyword module to view all the keywords available in your Python version.

Example:

python
CopyEdit
import keyword
print(keyword.kwlist) # Prints a list of all Python keywords
Tips for Using Keywords
1. Avoid using keywords as variable names:

python
CopyEdit
def = 10 # This will throw a SyntaxError because `def` is a keyword.

2. Remember case sensitivity:


o true is not a keyword (it's a variable name), but True is a keyword.
3. Use tools for checking keywords: The keyword module helps ensure your variable
names don't accidentally use reserved words.

Conclusion

Python keywords are essential for defining the structure, control flow, and logic of a program.
By understanding and effectively using them, you can write efficient, readable, and error-free
code. Always ensure you don’t use these reserved words as identifiers!
Control structures are the building blocks of any programming language, including Python. They
dictate the order in which instructions are executed, allowing for decision-making, repetition,
and more complex program flow. Here are the main types of control structures in Python :

Conditional statements are used to execute a block of code only if a specific condition is true.
They enable decision-making capabilities in a Python program.

Python supports the following conditional statements:

1. if Statement
The if statement executes a block of code only if a condition evaluates to True.

Syntax:

python
CopyEdit
if condition:
# Block of code

Example:

python
CopyEdit
age = 18
if age >= 18:
print("You are eligible to vote.")

 If the condition (age >= 18) is True, it will execute the code inside the if block.
 If the condition is False, it will skip the block.

2. if-else Statement
The if-else statement provides two paths: one for when the condition is True and another for
when it is False.

Syntax:

python
CopyEdit
if condition:
# Block of code if condition is True
else:
# Block of code if condition is False

Example:

python
CopyEdit
marks = 35
if marks >= 40:
print("You passed the exam.")
else:
print("You failed the exam.")

 If the condition (marks >= 40) is True, the if block executes.


 Otherwise, the else block executes.

3. if-elif-else Statement
The if-elif-else statement allows you to check multiple conditions. It evaluates each
condition in sequence until one is True. If none are True, the else block executes.

Syntax:

python
CopyEdit
if condition1:
# Block of code if condition1 is True
elif condition2:
# Block of code if condition2 is True
elif condition3:
# Block of code if condition3 is True
else:
# Block of code if none of the conditions are True

Example:

python
CopyEdit
marks = 75
if marks >= 90:
print("Grade: A+")
elif marks >= 80:
print("Grade: A")
elif marks >= 70:
print("Grade: B")
else:
print("Grade: C")

4. Nested if Statements
You can nest if statements to check multiple levels of conditions.

Syntax:

python
CopyEdit
if condition1:
if condition2:
# Block of code if both condition1 and condition2 are True

Example:

python
CopyEdit
age = 25
citizenship = "Indian"

if age >= 18:


if citizenship == "Indian":
print("You are eligible to vote in India.")
else:
print("You are not an Indian citizen.")
else:
print("You are not eligible to vote.")

5. Single-Line Conditional Statements


Python allows you to write conditional statements in a single line using the ternary operator.

Syntax:

python
CopyEdit
value = "True Condition" if condition else "False Condition"

Example:
python
CopyEdit
marks = 85
result = "Pass" if marks >= 40 else "Fail"
print(result)

6. Logical Operators in Conditions


You can use logical operators (and, or, not) to combine multiple conditions.

Using and

The condition evaluates to True only if all conditions are True.

python
CopyEdit
age = 20
if age >= 18 and age <= 30:
print("You are a young adult.")

Using or

The condition evaluates to True if at least one condition is True.

python
CopyEdit
day = "Saturday"
if day == "Saturday" or day == "Sunday":
print("It is the weekend.")

Using not

The condition evaluates to the opposite of the original condition.

python
CopyEdit
is_raining = False
if not is_raining:
print("You can go outside without an umbrella.")

7. Membership Operators in Conditions


You can check if an element exists in a sequence (like a list, string, or tuple).

Using in
python
CopyEdit
fruit = "apple"
if fruit in ["apple", "banana", "cherry"]:
print("The fruit is available.")

Using not in

python
CopyEdit
fruit = "mango"
if fruit not in ["apple", "banana", "cherry"]:
print("The fruit is not available.")

8. Best Practices for Conditional Statements


1. Indentation Matters:
o Python uses indentation to define the scope of a block.
o Always use consistent indentation (e.g., 4 spaces).
2. Simplify Complex Conditions:
o Use parentheses to make complex conditions more readable.
o Avoid overly nested if statements.
3. Avoid Redundancy:
o Check for common conditions first to reduce unnecessary comparisons.
4. Use Ternary Operators Sparingly:
o Avoid overusing single-line conditionals for complex logic.

Conclusion

Conditional statements are the backbone of decision-making in Python. They allow you to
control the flow of your program by executing specific blocks of code based on conditions.
Mastering these will enable you to handle diverse logic and build robust programs.

Let me know if you'd like to practice some problems or see examples for a specific use case!
A for loop in Python is used to iterate over a sequence (e.g., a list, tuple, string, dictionary, or
range) and execute a block of code for each element in the sequence. It is one of the most
commonly used looping structures in Python.

Syntax of for Loop


python
CopyEdit
for variable in sequence:
# Block of code (loop body)

 variable: This is the iterator that takes the value of each element in the sequence during each
iteration.
 sequence: The collection you want to loop over (e.g., list, string, or range).
 The loop body contains the statements to execute for each iteration.

1. Looping Through a List


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

Output:

CopyEdit
apple
banana
cherry

2. Looping Through a String


You can loop through each character in a string.

python
CopyEdit
for char in "Python":
print(char)
Output:

css
CopyEdit
P
y
t
h
o
n

3. Looping Through a Range


The range() function is commonly used with for loops to generate a sequence of numbers.

Example 1: Basic Range

python
CopyEdit
for i in range(5):
print(i)

Output:

CopyEdit
0
1
2
3
4

Example 2: Custom Start and End

python
CopyEdit
for i in range(2, 6):
print(i)

Output:

CopyEdit
2
3
4
5

Example 3: With Step

python
CopyEdit
for i in range(1, 10, 2):
print(i)

Output:

CopyEdit
1
3
5
7
9

4. Looping Through a Dictionary


You can use for loops to iterate over dictionary keys, values, or key-value pairs.

Loop Through Keys

python
CopyEdit
mydict = {"name": "Alice", "age": 25, "city": "New York"}
for key in mydict:
print(key)

Output:

CopyEdit
name
age
city

Loop Through Values

python
CopyEdit
for value in mydict.values():
print(value)

Output:

sql
CopyEdit
Alice
25
New York

Loop Through Key-Value Pairs

python
CopyEdit
for key, value in mydict.items():
print(key, ":", value)

Output:

yaml
CopyEdit
name : Alice
age : 25
city : New York

5. Nested for Loops


You can nest one for loop inside another to iterate through multiple sequences.

python
CopyEdit
for i in range(1, 4):
for j in range(1, 3):
print(f"Outer Loop: {i}, Inner Loop: {j}")

Output:

mathematica
CopyEdit
Outer Loop: 1, Inner Loop: 1
Outer Loop: 1, Inner Loop: 2
Outer Loop: 2, Inner Loop: 1
Outer Loop: 2, Inner Loop: 2
Outer Loop: 3, Inner Loop: 1
Outer Loop: 3, Inner Loop: 2

6. Using else with a for Loop


The else block in a for loop executes after the loop completes normally (i.e., without
encountering a break).

python
CopyEdit
for i in range(5):
print(i)
else:
print("Loop completed.")

Output:

vbnet
CopyEdit
0
1
2
3
4
Loop completed.

7. Using break and continue


 break: Terminates the loop prematurely.
 continue: Skips the current iteration and moves to the next.

Example of break

python
CopyEdit
for i in range(10):
if i == 5:
break
print(i)

Output:

CopyEdit
0
1
2
3
4

Example of continue

python
CopyEdit
for i in range(5):
if i == 2:
continue
print(i)

Output:

CopyEdit
0
1
3
4
8. Using for Loop with Enumerate
The enumerate() function provides both the index and the value during iteration.

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

Output:

CopyEdit
0 apple
1 banana
2 cherry

9. Using for Loop with List Comprehension


You can use for loops in list comprehensions to create lists in a compact form.

python
CopyEdit
squares = [x**2 for x in range(5)]
print(squares)

Output:

csharp
CopyEdit
[0, 1, 4, 9, 16]

Best Practices for for Loops

1. Avoid unnecessary iterations:


o Use break when you find the desired result.
2. Use descriptive variable names:
o Instead of for i in sequence, use meaningful names like for fruit in fruits.
3. Prefer comprehensions when applicable:
o Use list comprehensions for concise and readable code when creating new lists.
A while loop in Python is used to repeatedly execute a block of code as long as a given
condition is true. It is particularly useful when the number of iterations is not predetermined,
and the loop's execution depends on a condition.

Syntax of while Loop


python
CopyEdit
while condition:
# Code to execute (loop body)

 condition: A logical expression that evaluates to True or False.


 The loop will keep running as long as the condition is True.
 The loop stops when the condition evaluates to False.

1. Basic Example
python
CopyEdit
i = 1
while i <= 5:
print(i)
i += 1

Output:

CopyEdit
1
2
3
4
5

In this example:

 The loop starts with i = 1.


 It continues to run until i is greater than 5.
 i += 1 increments the value of i in each iteration.
2. Using else with while
A while loop can have an else block that executes after the loop terminates normally (i.e., not
terminated by a break statement).

python
CopyEdit
i = 1
while i <= 3:
print(i)
i += 1
else:
print("Loop completed!")

Output:

vbnet
CopyEdit
1
2
3
Loop completed!

3. Infinite while Loop


A while loop can run indefinitely if the condition never becomes False. Be cautious, as infinite
loops can cause your program to hang.

python
CopyEdit
while True:
print("This loop will run forever!")
break # Use break to exit the loop

Output:

arduino
CopyEdit
This loop will run forever!

4. Using break in a while Loop

The break statement is used to terminate the loop prematurely.

python
CopyEdit
i = 1
while i <= 5:
if i == 3:
break
print(i)
i += 1

Output:

CopyEdit
1
2

In this example, the loop stops when i equals 3 due to the break statement.

5. Using continue in a while Loop


The continue statement is used to skip the current iteration and move to the next one.

python
CopyEdit
i = 0
while i < 5:
i += 1
if i == 3:
continue
print(i)

Output:

CopyEdit
1
2
4
5

Here, when i equals 3, the continue statement skips the print statement for that iteration.

6. Example: Input Validation


A while loop is often used to repeatedly prompt the user until valid input is provided.

python
CopyEdit
password = ""
while password != "python123":
password = input("Enter the password: ")
print("Access granted!")

Output (example input):

mathematica
CopyEdit
Enter the password: test
Enter the password: python123
Access granted!

7. Nested while Loops


You can nest one while loop inside another.

python
CopyEdit
i = 1
while i <= 3:
j = 1
while j <= 2:
print(f"Outer loop: {i}, Inner loop: {j}")
j += 1
i += 1

Output:

mathematica
CopyEdit
Outer loop: 1, Inner loop: 1
Outer loop: 1, Inner loop: 2
Outer loop: 2, Inner loop: 1
Outer loop: 2, Inner loop: 2
Outer loop: 3, Inner loop: 1
Outer loop: 3, Inner loop: 2

8. Using while with a Counter


A counter is often used to limit the number of iterations in a while loop.

python
CopyEdit
counter = 0
while counter < 5:
print(f"Counter: {counter}")
counter += 1

Output:
makefile
CopyEdit
Counter: 0
Counter: 1
Counter: 2
Counter: 3
Counter: 4

9. Using while with a range()


You can combine a while loop with a manual counter to simulate the behavior of a for loop.

python
CopyEdit
i = 0
while i in range(5):
print(i)
i += 1

Output:

CopyEdit
0
1
2
3
4

10. Common Pitfalls


a. Forgetting to Update the Condition

If the condition is never updated, the loop will run indefinitely.

python
CopyEdit
i = 1
while i <= 5:
print(i) # This will cause an infinite loop because i is not
incremented.

To fix this, ensure that the condition changes within the loop.
b. Using the Wrong Condition

Ensure the condition reflects the desired logic.

python
CopyEdit
i = 1
while i > 0: # This condition will never terminate if i remains positive.
print(i)
i += 1

11. Real-World Applications of while Loop


 Input validation:

python
CopyEdit
user_input = ""
while not user_input.isdigit():
user_input = input("Enter a number: ")
print(f"You entered: {user_input}")

 Waiting for a Condition:

python
CopyEdit
import time

countdown = 5
while countdown > 0:
print(f"Time left: {countdown} seconds")
countdown -= 1
time.sleep(1) # Pause for 1 second
print("Time's up!")

Conclusion

The while loop in Python is a versatile construct that allows you to repeat code blocks as long as
a specific condition holds true. It is essential to understand how to manage the condition and use
control statements (break, continue) effectively to avoid infinite loops and achieve desired
functionality.
In Python, you can gather input from the user using the input() function. The input() function
allows you to prompt the user for information, and it returns the data as a string. Here's a detailed
explanation of how to work with user input in Python:

1. Basic User Input


The input() function reads a line of text entered by the user and returns it as a string.

Example:

python
CopyEdit
name = input("Enter your name: ")
print(f"Hello, {name}!")

 The program displays the prompt "Enter your name: ", and waits for the user to type
something.
 Whatever the user types is returned as a string and stored in the name variable.
 The program then prints a greeting using the value entered.

Sample Output:

mathematica
CopyEdit
Enter your name: Alice
Hello, Alice!

2. Converting User Input to Other Data Types


By default, the input() function always returns data as a string. If you want the input to be of
another data type (e.g., integer, float), you need to convert it explicitly using the appropriate type
conversion functions.

Example: Converting to Integer

python
CopyEdit
age = input("Enter your age: ")
age = int(age) # Convert the input to an integer
print(f"You are {age} years old.")

 Here, the input is converted to an integer using the int() function before it's used.
 If the user enters a non-numeric value, this will cause an error. You might want to handle that
using exception handling.
Example: Converting to Float

python
CopyEdit
height = input("Enter your height in meters: ")
height = float(height) # Convert the input to a float
print(f"Your height is {height} meters.")

3. Handling Invalid Input


Sometimes, users may enter invalid data (like non-numeric input when expecting a number). To
prevent the program from crashing, we can use exception handling to catch these errors.

Example with Exception Handling:

python
CopyEdit
try:
age = input("Enter your age: ")
age = int(age) # Try to convert to integer
print(f"You are {age} years old.")
except ValueError:
print("Please enter a valid number for age.")

 In this example, if the user enters something that can't be converted to an integer (e.g., "abc"),
the program catches the ValueError and prints a friendly message instead of crashing.

4. User Input with Multiple Values (Splitting Input)


If you want the user to enter multiple pieces of data in one line, you can use the split() method
to break the input string into a list of values.

Example:

python
CopyEdit
data = input("Enter your name, age, and city (separated by spaces): ")
name, age, city = data.split() # Split the input into three parts
print(f"Name: {name}, Age: {age}, City: {city}")

 The split() method splits the input string into a list of words based on spaces.
 We then unpack the list into the variables name, age, and city.

Sample Output:

yaml
CopyEdit
Enter your name, age, and city (separated by spaces): Alice 25 NewYork
Name: Alice, Age: 25, City: NewYork
5. Getting Input with Default Value
You can provide a default value when the user doesn't enter anything.

Example:

python
CopyEdit
name = input("Enter your name (default: John): ") or "John"
print(f"Hello, {name}!")

 If the user presses Enter without typing anything, the default value "John" is used.

Summary:

 Basic Input: Use input() to take input from the user.


 Type Conversion: Use functions like int(), float() to convert the input to other data types.
 Exception Handling: Use try and except to handle invalid input.
 Multiple Values: Use split() to handle multiple pieces of data entered in one line.
 Default Values: Use or to assign a default value if the user provides no input.

User input is a powerful way to make your Python programs interactive. Let me know if you'd
like to explore more examples or any specific scenario!
A function is a block of reusable code that performs a specific task. It allows you to group code
into a single entity, which can be executed whenever needed. Functions are useful for organizing
code, making it modular, and avoiding redundancy.

Functions can take inputs, perform operations, and return an output.

Why Use Functions?


Functions provide several benefits:

 Reusability: You write the function once and reuse it wherever needed in the program, reducing
code repetition.
 Modularity: Functions break large tasks into smaller, manageable chunks of code.
 Maintainability: Functions make it easier to update and maintain code since changes need to be
made in one place rather than throughout the entire program.
 Abstraction: Functions hide complex logic, allowing you to focus on higher-level tasks while
abstracting away the details.

Defining Functions: def function_name(parameters):


To define a function in Python, we use the def keyword, followed by the function name and any
parameters (optional). The body of the function is indented.

Example of a basic function definition:

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

 def is the keyword that begins the function definition.


 greet is the function name.
 name is the parameter the function accepts (this is an input to the function).
Calling Functions: function_name()
Once a function is defined, you can call it by its name and provide any necessary arguments.

python
CopyEdit
greet("Alice") # Output: Hello, Alice!

Here, the greet function is called with the argument "Alice", which is passed to the name
parameter.

Variable-length Arguments: *args and **kwargs


Sometimes, you might not know in advance how many arguments a function will receive. In
such cases, Python allows you to define functions that can accept a variable number of
arguments.

1. *args (Positional Arguments)

*args is used to pass a variable number of positional arguments to a function. Inside the
function, args will be a tuple containing all the arguments passed.

python
CopyEdit
def add(*args):
return sum(args)

print(add(1, 2, 3)) # Output: 6


print(add(10, 20)) # Output: 30

 In this example, *args collects all the positional arguments passed to the function and sums
them.

2. **kwargs (Keyword Arguments)

**kwargs allows you to pass a variable number of keyword arguments (key-value pairs) to a
function. Inside the function, kwargs will be a dictionary containing the arguments.

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

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


# Output:
# name: Alice
# age: 25
# city: New York
 **kwargs allows you to pass keyword arguments (like name, age, and city) in any order. The
function will access them by their names.

Hands-on Practice
1. Create a Simple Function

python
CopyEdit
def multiply(x, y):
return x * y

print(multiply(4, 5)) # Output: 20

 This function takes two parameters x and y, multiplies them, and returns the result.

2. Write Functions with Default Arguments

You can set default values for function parameters. If the caller doesn’t provide an argument, the
default value is used.

python
CopyEdit
def greet(name="Stranger"):
print(f"Hello, {name}!")

greet() # Output: Hello, Stranger!


greet("Bob") # Output: Hello, Bob!

 The function greet has a default argument "Stranger". If no name is provided when calling
the function, the default value is used.

3. Create Functions with a Variable Number of Arguments

 Using *args (Positional Arguments)

python
CopyEdit
def sum_numbers(*args):
return sum(args)

print(sum_numbers(1, 2, 3)) # Output: 6


print(sum_numbers(10, 20)) # Output: 30

 Using **kwargs (Keyword Arguments)

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

display_info(name="Alice", age=30)
# Output:
# name: Alice
# age: 30

In this example, **kwargs allows you to pass any number of key-value pairs, and the function
prints each pair.

In Python, function parameters are the variables that are defined inside the parentheses of a
function definition. When calling a function, you can pass values for these parameters. There are
different types of parameters that you can use to define functions. Here's an explanation of the
different types of function parameters:

1. Positional Arguments
Positional arguments are the most common type of arguments. They are passed to a function
based on their position. The values provided must match the order of parameters in the function
definition.

Example:

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

print(add(3, 4)) # Output: 7

 In the function add, the parameter a gets the value 3, and the parameter b gets the value 4.
 The function add(3, 4) works because the values are passed in the same order as the
parameters are defined.

2. Default Arguments
Default arguments are parameters that have a default value if no argument is passed during the
function call. You assign a default value to a parameter when defining the function. If the caller
does not provide a value for that parameter, the default value will be used.

Example:
python
CopyEdit
def greet(name="Stranger"):
print(f"Hello, {name}!")

greet() # Output: Hello, Stranger!


greet("Alice") # Output: Hello, Alice!

 In the function greet, the parameter name has a default value "Stranger".
 When calling greet(), no argument is provided, so "Stranger" is used as the default.
 When calling greet("Alice"), the function uses "Alice" as the value for name instead of
the default.

Important: Default arguments must be placed after positional arguments in the function
definition. Otherwise, you'll get a syntax error.

Example of incorrect order:

python
CopyEdit
# This will raise a SyntaxError
def greet(name="Stranger", age):
print(f"Hello {name}, you are {age} years old.")

To fix this, ensure default arguments come last:

python
CopyEdit
def greet(age, name="Stranger"):
print(f"Hello {name}, you are {age} years old.")

3. Keyword Arguments
Keyword arguments are passed to a function by explicitly specifying the parameter name along
with its value. You can pass keyword arguments in any order as long as you specify the
parameter name when calling the function.

Example:

python
CopyEdit
def greet(name, age):
print(f"Hello {name}, you are {age} years old.")

greet(name="Alice", age=30) # Output: Hello Alice, you are 30 years old.


greet(age=25, name="Bob") # Output: Hello Bob, you are 25 years old.

 In the function call greet(name="Alice", age=30), the argument name is explicitly passed
with the value "Alice", and age is explicitly passed with 30.
 You can change the order of the arguments when using keyword arguments because Python can
match each argument with the corresponding parameter by name.

Summary of Function Parameter Types:

 Positional Arguments: The values are assigned to parameters based on their position.
o Example: greet("Alice", 25) → name="Alice", age=25
 Default Arguments: Parameters that have default values if no argument is provided for
them.
o Example: def greet(name="Stranger") → "Stranger" is used if name is not
passed.
 Keyword Arguments: Arguments passed by explicitly specifying the parameter name.
o Example: greet(age=25, name="Alice") → The order of arguments can vary.

A More Complex Example:


python
CopyEdit
def describe_person(name, age=30, city="Unknown"):
print(f"Name: {name}, Age: {age}, City: {city}")

describe_person("Alice") # Output: Name: Alice, Age: 30, City:


Unknown
describe_person("Bob", 35) # Output: Name: Bob, Age: 35, City: Unknown
describe_person("Charlie", 40, "New York") # Output: Name: Charlie, Age: 40,
City: New York

 In this case:
o name is a positional argument.
o age and city are default arguments.
o You can provide values for age and city, or use the default ones.

Let me know if you'd like further clarification or examples!


Functions in Python not only perform operations but also have the capability to return values to
the calling code. The return statement is used to send a result back from a function to the caller.

Let’s break down the concept of returning values from functions in Python:

1. Returning a Single Value


When a function performs a calculation or operation, you can use the return keyword to send
the result back to the calling code. This allows you to use the function’s result elsewhere in your
program.

Example: Returning a Single Value

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

result = add(5, 3)
print(result) # Output: 8

 The function add takes two parameters a and b, adds them, and returns the result.
 The result of the function call add(5, 3) is stored in the variable result, and then printed.

In this case, the function returns a single value (the sum of a and b).

2. Returning Multiple Values


Functions in Python can return multiple values at once. Python does this by returning a tuple (an
ordered collection of values).

Example: Returning Multiple Values (Tuple)

python
CopyEdit
def get_coordinates():
return 10, 20 # Returns a tuple (10, 20)

x, y = get_coordinates() # Unpack the returned tuple


print(f"x: {x}, y: {y}") # Output: x: 10, y: 20
 The function get_coordinates returns two values: 10 and 20, which are packed into a tuple.
 When calling get_coordinates(), we unpack the tuple into the variables x and y.

This makes it easy to return multiple related values from a function.

3. Returning Values in Different Formats


Functions can return values in various formats like lists, dictionaries, and even tuples,
depending on the needs of your program. Let’s look at how functions can return these formats.

Returning a List

You can return a list if you need to return multiple items of the same type.

python
CopyEdit
def get_even_numbers(n):
even_numbers = []
for i in range(n):
if i % 2 == 0:
even_numbers.append(i)
return even_numbers

result = get_even_numbers(10)
print(result) # Output: [0, 2, 4, 6, 8]

 The function get_even_numbers creates a list of even numbers up to a specified number n.


 It returns the list of even numbers as the result.

Returning a Dictionary

If you need to return data in key-value pairs, you can return a dictionary. This is useful when
each value is associated with a unique key.

python
CopyEdit
def get_person_info(name, age, city):
return {"name": name, "age": age, "city": city}

person = get_person_info("Alice", 30, "New York")


print(person)
# Output: {'name': 'Alice', 'age': 30, 'city': 'New York'}

 The function get_person_info takes three parameters and returns a dictionary where the
keys are "name", "age", and "city".
 The dictionary is returned with the corresponding values.
Returning a Tuple

As mentioned earlier, functions can return tuples. This is useful when you need to return multiple
values of potentially different types, grouped together.

python
CopyEdit
def calculate_area_and_perimeter(length, width):
area = length * width
perimeter = 2 * (length + width)
return area, perimeter # Returns a tuple (area, perimeter)

area, perimeter = calculate_area_and_perimeter(5, 3)


print(f"Area: {area}, Perimeter: {perimeter}")
# Output: Area: 15, Perimeter: 16

 The function calculate_area_and_perimeter returns two values: area and perimeter,


as a tuple.
 The calling code unpacks the tuple into the variables area and perimeter.

4. Hands-on Practice:
a. Returning Multiple Values

python
CopyEdit
def get_max_and_min(numbers):
max_value = max(numbers)
min_value = min(numbers)
return max_value, min_value # Returns a tuple (max_value, min_value)

numbers = [3, 1, 4, 1, 5, 9]
maximum, minimum = get_max_and_min(numbers)
print(f"Maximum: {maximum}, Minimum: {minimum}")
# Output: Maximum: 9, Minimum: 1

 This function takes a list of numbers and returns the maximum and minimum values as a tuple.
The values are then unpacked into maximum and minimum.

b. Returning a List

python
CopyEdit
def get_prime_numbers(limit):
primes = []
for num in range(2, limit):
is_prime = True
for i in range(2, int(num ** 0.5) + 1):
if num % i == 0:
is_prime = False
break
if is_prime:
primes.append(num)
return primes

primes_up_to_20 = get_prime_numbers(20)
print(primes_up_to_20)
# Output: [2, 3, 5, 7, 11, 13, 17, 19]

 The function get_prime_numbers returns a list of prime numbers up to a given limit.

c. Returning a Dictionary

python
CopyEdit
def get_user_info(name, age, city):
return {"Name": name, "Age": age, "City": city}

user_info = get_user_info("Bob", 25, "London")


print(user_info)
# Output: {'Name': 'Bob', 'Age': 25, 'City': 'London'}

 The function get_user_info returns a dictionary with the user's details.

Summary:

 Returning a Single Value: You can return one value from a function using the return keyword.
 Returning Multiple Values: Functions can return multiple values by packing them into a tuple.
 Returning Other Formats: Functions can return different data structures like lists, dictionaries,
or tuples.
 Unpacking Return Values: You can unpack returned values (e.g., a tuple) into separate variables
for ease of use.

In Python, the scope and lifetime of variables are important concepts that determine where a
variable can be accessed from and how long it remains in memory. Let's break these down with
respect to functions.
1. Scope: Where a Variable Can Be Accessed
The scope of a variable refers to the context in which the variable is accessible in the code.
Python has two primary types of scopes:

 Local Scope: A variable defined inside a function is in local scope. This means the
variable can only be accessed within that function.
 Global Scope: A variable defined outside of all functions is in global scope. This means
the variable is accessible anywhere in the code, including inside functions (with some
rules).

Local Scope (Function-level scope)

Variables defined inside a function are local variables, meaning they can only be accessed
within that function. Once the function finishes execution, the local variables are destroyed and
are no longer accessible.

Example:

python
CopyEdit
def my_function():
x = 10 # Local variable
print(x)

my_function() # Output: 10
# print(x) # This will cause an error because x is a local variable to
my_function.

 x is a local variable inside my_function. It's accessible only within that function.
 Trying to access x outside the function would result in a NameError because it is out of scope.

Global Scope (Program-level scope)

Variables defined outside of functions are global variables and can be accessed from anywhere
in the program, including inside functions.

Example:

python
CopyEdit
x = 20 # Global variable

def my_function():
print(x) # Accessing the global variable

my_function() # Output: 20
 The variable x is defined outside the function and is a global variable.
 You can access it inside the function my_function().

2. Lifetime: How Long a Variable Exists


The lifetime of a variable refers to how long the variable remains in memory. It depends on its
scope.

 Local Variables: The lifetime of a local variable begins when the function is called and
ends when the function finishes execution. Once the function completes, the local
variables are discarded and no longer exist.
 Global Variables: The lifetime of a global variable lasts as long as the program is
running. It exists for the entire duration of the program, from the point it is defined until
the program terminates.

Example of Lifetime:

python
CopyEdit
def my_function():
a = 10 # Local variable
print(a)

my_function()
# print(a) # This will raise an error because 'a' no longer exists outside
the function.

 The variable a is created when my_function() is called and is destroyed when the function
ends.
 After the function ends, a no longer exists.

3. Modifying Global Variables Inside Functions


You can modify global variables inside a function, but Python treats any variable assigned inside
a function as local by default. If you want to modify a global variable inside a function, you need
to use the global keyword.

Example of Modifying Global Variables:

python
CopyEdit
x = 5 # Global variable

def modify_global():
global x # Declare x as global inside the function
x = 10 # Modify the global variable
print(x) # Output: 5 (before modification)
modify_global()
print(x) # Output: 10 (after modification)

 The global keyword tells Python that x refers to the global variable and not a local one.
 Without the global keyword, Python would create a new local variable x inside the function,
and the global variable would remain unchanged.

Example without global keyword (creating a local variable):

python
CopyEdit
x = 5

def modify_local():
x = 10 # Local variable (does not affect the global x)
print("Inside function:", x)

modify_local()
print("Outside function:", x) # Output: 5 (global x is unchanged)

 The x inside the function is a local variable and does not affect the global x.
 The global x remains unchanged after calling modify_local().

4. Hands-on Practice: Local vs Global Variables


Example 1: Modifying a Global Variable Inside a Function

python
CopyEdit
y = 50 # Global variable

def increase_y():
global y # Declare y as global
y += 10 # Modify the global variable

print("Before function call:", y) # Output: 50


increase_y()
print("After function call:", y) # Output: 60

 Here, we used the global keyword to modify the global variable y inside the increase_y()
function.

Example 2: Accessing a Global Variable Inside a Function (Without Modifying It)

python
CopyEdit
z = 100 # Global variable
def print_z():
print("Global z inside function:", z)

print_z() # Output: Global z inside function: 100


print("Global z outside function:", z) # Output: Global z outside function:
100

 In this case, we accessed the global variable z inside the function but did not modify it. The
global variable remains the same outside the function.

Example 3: Local Variables (Lifetime)

python
CopyEdit
def local_variable_example():
a = 200 # Local variable
print("Inside function:", a)

local_variable_example() # Output: Inside function: 200


# print(a) # This will raise an error because 'a' does not exist outside the
function.

 The variable a is local to the function local_variable_example, and its lifetime is limited to
the execution of that function.

Key Points:

 Local Scope: Variables defined inside a function are local and can only be accessed within that
function.
 Global Scope: Variables defined outside of all functions are global and can be accessed
anywhere in the code.
 Lifetime:
o Local variables are created when a function is called and destroyed when the function
finishes execution.
o Global variables remain in memory for the entire duration of the program.
 Modifying Global Variables: To modify a global variable inside a function, use the global
keyword.
 Local vs Global Variables: A variable inside a function is local unless explicitly declared as global.
Recursion is a programming technique where a function calls itself in order to solve a problem.
A recursive function typically has two main parts:

1. Base Case: A condition that stops the recursion.


2. Recursive Case: The function calls itself with a modified argument to progress towards the base
case.

1. What is Recursion?

Recursion occurs when a function calls itself to solve smaller instances of a problem. It's a
powerful tool, often used for problems that can be broken down into smaller, similar
subproblems.

Example of Recursion:

 A simple example of recursion is a function that calls itself to calculate the factorial of a number.

2. Advantages of Recursion
 Simplifies Complex Problems: Recursion can make certain problems easier to solve. Problems
that involve repetitive tasks, such as traversing trees or solving puzzles like the Tower of Hanoi,
can be naturally solved with recursion.
 Code Readability: Recursive functions tend to be shorter and easier to understand when
compared to iterative solutions (loops), especially for problems like searching or sorting.
 Elegant Solution: Many algorithms, like Depth First Search (DFS), are more intuitive and easier
to implement recursively.

3. Disadvantages of Recursion
 Stack Overflow: Recursion uses the call stack to keep track of function calls. If the recursion
goes too deep (i.e., there are too many recursive calls without hitting the base case), it can
cause a stack overflow, which results in an error.
 Memory Usage: Since each recursive call creates a new function call, it can consume more
memory compared to an iterative approach.
 Performance Overhead: Recursive functions can sometimes be less efficient than iterative
solutions because of the overhead involved in making function calls and maintaining the call
stack.
4. Hands-on Practice: Recursive Functions for Factorial and
Fibonacci
Let’s look at some practical examples of recursion: Factorial and Fibonacci series.

4.1 Recursive Function for Factorial

The factorial of a number n is the product of all positive integers less than or equal to n. The
formula for the factorial is:

scss
CopyEdit
n! = n * (n - 1) * (n - 2) * ... * 1

Factorial can be computed recursively using the relation:

scss
CopyEdit
n! = n * (n-1)!

The base case is 0! = 1.

Recursive Factorial Function Example:

python
CopyEdit
def factorial(n):
# Base Case: if n is 0 or 1, return 1
if n == 0 or n == 1:
return 1
# Recursive Case: n * factorial of (n - 1)
else:
return n * factorial(n - 1)

# Test the function


print(factorial(5)) # Output: 120

 Base Case: When n == 0 or n == 1, the function returns 1.


 Recursive Case: The function calls itself with n - 1 and multiplies n by the result of that call.

Sample Execution:

For factorial(5):

1. factorial(5) calls factorial(4), which calls factorial(3), which calls factorial(2),


and so on.
2. When n reaches 1, the base case is met, and the function begins returning values, ultimately
calculating 5 * 4 * 3 * 2 * 1

4.2 Recursive Function for Fibonacci Series

The Fibonacci series is a sequence of numbers where each number is the sum of the two
preceding ones. The sequence starts with 0 and 1, and the next number is obtained by adding the
previous two numbers.

The Fibonacci sequence is defined as:

scss
CopyEdit
F(0) = 0, F(1) = 1
F(n) = F(n-1) + F(n-2) for n > 1

Recursive Fibonacci Function Example:

python
CopyEdit
def fibonacci(n):
# Base Case: F(0) = 0, F(1) = 1
if n == 0:
return 0
elif n == 1:
return 1
# Recursive Case: F(n) = F(n-1) + F(n-2)
else:
return fibonacci(n - 1) + fibonacci(n - 2)

# Test the function


print(fibonacci(6)) # Output: 8

 Base Cases: fibonacci(0) = 0 and fibonacci(1) = 1.


 Recursive Case: The function calls itself twice, once with n - 1 and once with n - 2, and adds
the results.

Sample Execution:

For fibonacci(6):

1. fibonacci(6) calls fibonacci(5) and fibonacci(4), and so on.


2. The function eventually reaches the base cases (fibonacci(0) and fibonacci(1)), and the
values are returned and added together to calculate the result.
5. Illustration of Recursive Call Stack
For factorial(5):

scss
CopyEdit
factorial(5) → 5 * factorial(4)
factorial(4) → 4 * factorial(3)
factorial(3) → 3 * factorial(2)
factorial(2) → 2 * factorial(1)
factorial(1) → 1 (base case)

After reaching the base case, the function starts returning the results:

scss
CopyEdit
factorial(1) = 1
factorial(2) = 2 * 1 = 2
factorial(3) = 3 * 2 = 6
factorial(4) = 4 * 6 = 24
factorial(5) = 5 * 24 = 120

For fibonacci(6):

scss
CopyEdit
fibonacci(6) → fibonacci(5) + fibonacci(4)
fibonacci(5) → fibonacci(4) + fibonacci(3)
fibonacci(4) → fibonacci(3) + fibonacci(2)
fibonacci(3) → fibonacci(2) + fibonacci(1)
fibonacci(2) → fibonacci(1) + fibonacci(0)
fibonacci(1) = 1 (base case)
fibonacci(0) = 0 (base case)

Then the results are added:

scss
CopyEdit
fibonacci(0) = 0
fibonacci(1) = 1
fibonacci(2) = 1 (1 + 0)
fibonacci(3) = 2 (1 + 1)
fibonacci(4) = 3 (2 + 1)
fibonacci(5) = 5 (3 + 2)
fibonacci(6) = 8 (5 + 3)
6. Limitations and Optimization
 Stack Overflow: If the recursion goes too deep, the Python interpreter will throw a
RecursionError due to the depth limit of the call stack.
o You can adjust the recursion depth limit using sys.setrecursionlimit() but be
cautious about using very high limits.
 Memoization (Optimization): To avoid repeated calculations, especially in functions like
Fibonacci, we can optimize recursion using memoization. This involves storing results of
previous calls so that they can be reused, thus improving performance.

Example of Optimized Fibonacci with Memoization:

python
CopyEdit
def fibonacci_memo(n, memo={}):
if n in memo:
return memo[n]
if n == 0:
return 0
elif n == 1:
return 1
memo[n] = fibonacci_memo(n - 1, memo) + fibonacci_memo(n - 2, memo)
return memo[n]

print(fibonacci_memo(6)) # Output: 8

 This reduces the number of recursive calls, improving the function's efficiency.

Summary:

 Recursion involves a function calling itself to solve smaller instances of a problem.


 Base Case stops the recursion.
 Recursive Case continues the recursion by calling the function again.
 Advantages: Recursion simplifies problems that have a repetitive or nested structure (like
Factorial, Fibonacci).
 Disadvantages: Excessive recursion can cause a stack overflow and consume more memory.
 Optimization: Memoization can optimize recursive functions to avoid redundant calculations.
Lambda functions are a special type of function in Python that are defined without a name.
They are also known as anonymous functions. Lambda functions are useful when you need a
simple, one-line function for a short task, and they can often make your code more concise and
readable.

1. What are Lambda Functions?


Lambda functions are created using the lambda keyword followed by one or more arguments, a
colon (:), and an expression. The result of the expression is implicitly returned by the function.

The general syntax for a lambda function is:

python
CopyEdit
lambda arguments: expression

 Arguments: The input parameters (like those in a normal function).


 Expression: A single expression whose result is automatically returned when the function is
called.

Unlike regular functions created with the def keyword, lambda functions are typically written in
a single line and do not have a name.

Example:

python
CopyEdit
add = lambda x, y: x + y
print(add(2, 3)) # Output: 5

In the above example:

 lambda x, y defines the input arguments x and y.


 x + y is the expression that gets returned.

2. Common Use Cases of Lambda Functions


Lambda functions are commonly used in situations where a small function is needed temporarily
for tasks like sorting, mapping, and filtering. They provide a concise way of defining simple
functions for these operations without the need for a full function definition.
2.1 Sorting with Lambda Functions

Sorting is one of the most common use cases of lambda functions. If you want to sort a list of
items based on some criteria, you can use a lambda function as the sorting key.

Example: Sorting a list of tuples based on the second element:


python
CopyEdit
# List of tuples (name, age)
people = [("John", 25), ("Alice", 30), ("Bob", 20)]

# Sorting by age (second element of the tuple)


sorted_people = sorted(people, key=lambda person: person[1])
print(sorted_people) # Output: [('Bob', 20), ('John', 25), ('Alice', 30)]

 The lambda function lambda person: person[1] returns the second element (the age) of
each tuple, and the sorted() function uses this value to sort the list.

2.2 Mapping with Lambda Functions

Mapping involves applying a function to each element of a list or any other iterable. The map()
function in Python can be used with lambda functions to apply the operation to each element.

Example: Using map() to square each number in a list:


python
CopyEdit
numbers = [1, 2, 3, 4, 5]

# Using map() with a lambda function to square each number


squared_numbers = list(map(lambda x: x ** 2, numbers))
print(squared_numbers) # Output: [1, 4, 9, 16, 25]

 The lambda function lambda x: x ** 2 squares each element in the list numbers.

2.3 Filtering with Lambda Functions

Filtering involves selecting elements from a collection that satisfy a condition. The filter()
function in Python allows you to filter elements of an iterable using a lambda function that
specifies the condition.

Example: Using filter() to get even numbers:


python
CopyEdit
numbers = [1, 2, 3, 4, 5, 6]

# Using filter() with a lambda function to get even numbers


even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers) # Output: [2, 4, 6]
 The lambda function lambda x: x % 2 == 0 checks whether each element in numbers is
even.

3. Hands-on Practice: Writing Simple Lambda Functions


Let's go over some practical examples to illustrate different ways lambda functions can be used
for basic tasks.

Example 1: Addition (Simple Lambda)

A simple lambda function that adds two numbers together.

python
CopyEdit
# Lambda function for addition
add = lambda x, y: x + y
print(add(10, 20)) # Output: 30

 The lambda function lambda x, y: x + y performs the addition of x and y.

Example 2: Multiplication (Simple Lambda)

A lambda function to multiply two numbers.

python
CopyEdit
# Lambda function for multiplication
multiply = lambda x, y: x * y
print(multiply(3, 4)) # Output: 12

 The lambda function lambda x, y: x * y multiplies x and y.

Example 3: Sorting a List of Strings by Length

We can use a lambda function to sort a list of strings by their length.

python
CopyEdit
# List of strings
words = ["apple", "banana", "cherry", "date"]

# Sorting the list by length of the words


sorted_words = sorted(words, key=lambda word: len(word))
print(sorted_words) # Output: ['date', 'apple', 'cherry', 'banana']

 The lambda function lambda word: len(word) sorts the words by their length.
Example 4: Filtering Even Numbers

Use a lambda function to filter out even numbers from a list.

python
CopyEdit
numbers = [1, 2, 3, 4, 5, 6]

# Filtering even numbers using filter() and lambda


even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers) # Output: [2, 4, 6]

 The lambda function lambda x: x % 2 == 0 returns True for even numbers, filtering out
odd numbers.

Example 5: Mapping to Square Numbers

Use a lambda function to square each number in a list using map().

python
CopyEdit
numbers = [1, 2, 3, 4, 5]

# Squaring each number in the list using map() and lambda


squared_numbers = list(map(lambda x: x ** 2, numbers))
print(squared_numbers) # Output: [1, 4, 9, 16, 25]

 The lambda function lambda x: x ** 2 squares each number in the list.

Summary of Lambda Functions

 Lambda Function Syntax: lambda arguments: expression.


 Key Characteristics:
o Anonymous (not bound to a name).
o Can only contain a single expression.
o Useful in situations where a simple, short function is required.
 Common Use Cases:
o Sorting: Sort collections by specific criteria.
o Mapping: Apply a transformation to each element in a collection.
o Filtering: Filter elements of a collection based on a condition.

Lambda functions are particularly useful when you want to define a small function inline,
without the need for a full function definition using def.
In Python, functions are first-class objects, meaning they can be passed around, returned from
other functions, and modified dynamically. This leads to some advanced concepts like
decorators and closures, which allow for more flexible and dynamic behavior. Let’s explore
these concepts in detail:

1. Function Wrapping with Decorators


A decorator is a function that modifies or enhances another function or method. It allows us to
wrap a function in order to add extra behavior without changing the original function's code.
Decorators are commonly used in logging, authentication, timing, and many other areas.

1.1 What is a Decorator?

A decorator is a function that takes another function as input, and returns a new function that
typically calls the original function, possibly modifying its input or output. This allows you to
extend or alter the behavior of a function without permanently modifying the original function.

1.2 How Decorators Work

In Python, decorators are typically used with the @decorator_name syntax, placed above the
function definition that you want to decorate.

Here’s a simple structure:

python
CopyEdit
def decorator_function(original_function):
def wrapper_function():
print("Function wrapped")
return original_function() # Call the original function
return wrapper_function

You can then use the decorator with the @ symbol:

python
CopyEdit
@decorator_function
def say_hello():
print("Hello!")

say_hello()

The output will be:

javascript
CopyEdit
Function wrapped
Hello!

1.3 Example of a Simple Decorator

Here’s a real-world example of a decorator that logs function execution:

python
CopyEdit
def logger_decorator(func):
def wrapper():
print(f"Calling function {func.__name__}")
result = func() # Call the original function
print(f"{func.__name__} executed successfully")
return result
return wrapper

@logger_decorator
def greet():
print("Hello, World!")

greet()

Output:

bash
CopyEdit
Calling function greet
Hello, World!
greet executed successfully

 logger_decorator is the decorator function.


 greet is the decorated function.
 The decorator adds logging functionality before and after calling the greet function.

1.4 Decorators with Arguments

If the function being decorated takes arguments, the decorator must be modified to accept them
as well. This is done by using *args and **kwargs to pass any arguments dynamically.

Here’s an example of a decorator that takes arguments:

python
CopyEdit
def repeat_decorator(func):
def wrapper(*args, **kwargs):
print("Repeating function call...")
return func(*args, **kwargs)
return wrapper

@repeat_decorator
def say_hello(name):
print(f"Hello, {name}!")

say_hello("Alice")

Output:

vbnet
CopyEdit
Repeating function call...
Hello, Alice!

2. Function Closures
A closure is a function that "remembers" the values from the enclosing function even after the
enclosing function has finished execution. This means that the closure function has access to the
variables from its enclosing (outer) function even after it has returned.

A closure occurs when:

1. A function is defined inside another function.


2. The inner function refers to variables from the outer function.

2.1 How Closures Work

In the following example, the inner function (closure) remembers the variable x even after the
outer function finishes execution.

python
CopyEdit
def outer_function(x):
def inner_function(y):
return x + y
return inner_function

closure = outer_function(10)
print(closure(5)) # Output: 15

Explanation:

 outer_function(10) returns inner_function, but with x set to 10.


 closure(5) calls the inner function with y = 5, so it returns 10 + 5 = 15.

The key idea is that the inner function remembers the value of x even after the outer function
has finished execution. This is a closure.

2.2 Closures with Stateful Behavior


You can use closures to maintain a state across multiple function calls. Here’s an example of a
closure that counts the number of times it’s called:

python
CopyEdit
def counter():
count = 0
def increment():
nonlocal count # Access the variable from the outer function
count += 1
return count
return increment

count_function = counter()

print(count_function()) # Output: 1
print(count_function()) # Output: 2
print(count_function()) # Output: 3

Explanation:

 counter() is the outer function that defines count and increment.


 increment() is the closure that remembers the state of count.
 Each time count_function() is called, count is incremented, and the state is preserved
across calls.

3. Hands-on Practice: Implementing Decorators and Writing Closures

3.1 Implementing a Decorator for Timing

Let’s create a decorator to measure the execution time of a function.

python
CopyEdit
import time

def timing_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs) # Call the original function
end_time = time.time()
print(f"{func.__name__} executed in {end_time - start_time:.4f}
seconds")
return result
return wrapper

@timing_decorator
def slow_function():
time.sleep(2)
print("Function finished!")

slow_function()
Output:

javascript
CopyEdit
Function finished!
slow_function executed in 2.0001 seconds

 The timing_decorator adds timing functionality to the slow_function.

3.2 Writing Closures to Remember a State

We’ll write a closure to remember the total sum of all numbers passed to it.

python
CopyEdit
def sum_closure():
total = 0
def add_to_sum(x):
nonlocal total
total += x
return total
return add_to_sum

sum_function = sum_closure()

print(sum_function(10)) # Output: 10
print(sum_function(20)) # Output: 30
print(sum_function(5)) # Output: 35

Explanation:

 sum_closure() creates a closure add_to_sum() that remembers the state of total and
adds the passed value to it.
 The nonlocal keyword ensures that the total variable from the enclosing scope is modified
inside the closure.

Summary of Advanced Function Techniques

 Decorators: Functions that wrap other functions to modify or enhance their behavior. Common
use cases include logging, caching, and access control.
o Syntax: @decorator_name
o Decorators can take arguments and return results.
 Closures: Functions that remember the variables from their enclosing function even after the
outer function has returned. They allow us to maintain state across multiple calls.
o Closures are often used for counters, maintaining state, or for function factories.
 Practical Examples: You can use decorators to log function calls, measure execution time, or
manage caching. Closures are useful for maintaining state between function calls, such as
creating a counter or managing a running total.
In Python, error handling is a way of gracefully dealing with unexpected situations (exceptions)
that occur during the execution of a program. This is particularly important in functions, as they
may encounter errors due to invalid inputs, unexpected conditions, or other issues. Python
provides a robust mechanism for error handling using the try, except, else, and finally
blocks, along with the ability to raise custom exceptions.

1. Exception Handling: try, except, else, and finally

1.1 What is Exception Handling?

Exception handling is used to catch and handle errors (exceptions) in a way that allows the
program to continue running smoothly. If an error occurs in a part of the program, the normal
flow is interrupted, but with exception handling, we can "catch" the error, handle it, and even
proceed with alternative actions.

1.2 Syntax of try, except, else, and finally

The basic structure for handling exceptions is:

python
CopyEdit
try:
# Code that might raise an exception
except SomeException as e:
# Code to handle the exception
else:
# Code to run if no exception occurs
finally:
# Code that runs no matter what

 try: This block contains the code that might raise an exception. If an exception is raised here,
Python will look for an appropriate except block.
 except: If an exception occurs in the try block, it is caught here. You can catch specific
exceptions, or catch all exceptions.
 else: This block is executed if no exception occurs in the try block. It's optional but useful for
clean-up or post-processing tasks.
 finally: This block is executed regardless of whether an exception occurred or not. It is often
used for clean-up tasks, such as closing files or releasing resources.

1.3 Example: Basic Exception Handling

Here’s an example of how to use try, except, else, and finally:

python
CopyEdit
def divide_numbers(a, b):
try:
result = a / b
except ZeroDivisionError as e:
print(f"Error: {e}")
else:
print(f"Division successful, result is: {result}")
finally:
print("Execution completed.")

divide_numbers(10, 2)
divide_numbers(10, 0)

Output:

vbnet
CopyEdit
Division successful, result is: 5.0
Execution completed.
Error: division by zero
Execution completed.

 In the first call, the division is successful, and the else block is executed.
 In the second call, a ZeroDivisionError is raised, and the except block catches and handles
the error.

1.4 Handling Multiple Exceptions

You can catch multiple types of exceptions by adding multiple except blocks.

python
CopyEdit
def safe_divide(a, b):
try:
return a / b
except ZeroDivisionError:
print("Cannot divide by zero!")
except TypeError:
print("Both inputs must be numbers!")
else:
print("Division was successful!")

safe_divide(10, 0) # Cannot divide by zero!


safe_divide(10, 'a') # Both inputs must be numbers!

2. Raising Custom Exceptions with raise

Sometimes, you may want to manually trigger an exception if certain conditions are met. You
can use the raise keyword to raise a custom exception.

2.1 Syntax of raise


The syntax for raising an exception is:

python
CopyEdit
raise Exception("Error message")

You can also define your own custom exception class by inheriting from Python’s built-in
Exception class.

2.2 Example of Raising a Custom Exception

Here’s an example of how to define and raise a custom exception:

python
CopyEdit
class NegativeNumberError(Exception):
"""Custom exception raised when a negative number is provided."""
pass

def check_positive_number(number):
if number < 0:
raise NegativeNumberError("Negative number is not allowed.")
else:
print(f"Number {number} is valid.")

try:
check_positive_number(-5)
except NegativeNumberError as e:
print(f"Error: {e}")

Output:

typescript
CopyEdit
Error: Negative number is not allowed.

In this example:

 A custom exception NegativeNumberError is defined by subclassing the Exception class.


 The function check_positive_number raises the custom exception if the number is negative.
 The exception is caught and handled in the except block.

2.3 Raising Built-in Exceptions

You can also raise built-in exceptions when necessary. For example, raising a ValueError if the
input is not valid:

python
CopyEdit
def check_age(age):
if age < 18:
raise ValueError("Age must be 18 or older.")
print("Age is valid.")

try:
check_age(15)
except ValueError as e:
print(f"Error: {e}")

Output:

javascript
CopyEdit
Error: Age must be 18 or older.

3. Hands-on Practice: Implementing Error Handling and Raising Custom


Exceptions

3.1 Example 1: Error Handling in a Function

Let's write a function to calculate the square root of a number and handle invalid inputs like
negative numbers or non-numeric inputs.

python
CopyEdit
import math

def calculate_square_root(value):
try:
if value < 0:
raise ValueError("Cannot calculate square root of a negative
number.")
return math.sqrt(value)
except ValueError as e:
print(f"Error: {e}")
except TypeError:
print("Error: Input must be a number.")
else:
print("Square root calculated successfully.")
finally:
print("Function execution completed.")

calculate_square_root(16)
calculate_square_root(-4)
calculate_square_root("hello")

Output:

typescript
CopyEdit
Square root calculated successfully.
Function execution completed.
Error: Cannot calculate square root of a negative number.
Function execution completed.
Error: Input must be a number.
Function execution completed.

 We check if the input is a negative number and raise a ValueError if it is.


 We catch both ValueError and TypeError and print appropriate error messages.

3.2 Example 2: Raising Custom Exceptions

Let’s raise a custom exception when trying to withdraw an amount greater than the account
balance:

python
CopyEdit
class InsufficientFundsError(Exception):
"""Custom exception for insufficient funds."""
pass

def withdraw(balance, amount):


if amount > balance:
raise InsufficientFundsError("Insufficient funds in your account.")
return balance - amount

try:
balance = 500
balance = withdraw(balance, 600)
except InsufficientFundsError as e:
print(f"Error: {e}")
else:
print(f"Withdrawal successful. New balance is {balance}.")

Output:

javascript
CopyEdit
Error: Insufficient funds in your account.

 The InsufficientFundsError is raised if the withdrawal amount exceeds the balance, and
the error is caught and printed.

Summary of Error Handling in Functions

 try, except, else, and finally are used for catching and handling exceptions, allowing the
program to continue running or clean up resources even if an error occurs.
 Raising Exceptions: Use the raise keyword to raise built-in or custom exceptions when a
function or program encounters an error condition.
o Custom exceptions can be defined by subclassing the Exception class.
 Handling Multiple Exceptions: You can use multiple except blocks to handle different types of
exceptions.
 finally Block: Code inside finally will always run, regardless of whether an exception
occurred or not. This is ideal for cleanup tasks.
In Python, exception handling is used to handle runtime errors gracefully instead of crashing the
program. The try-except block allows us to catch errors and take appropriate actions.

🔹 What is an Exception?

An exception is an error that occurs during program execution. Common examples include:
✅ ZeroDivisionError – Dividing by zero
✅ ValueError – Invalid data type conversion
✅ FileNotFoundError – Trying to open a missing file
✅ IndexError – Accessing an out-of-range index in a list

Instead of stopping the program abruptly, Python provides try-except to handle these
exceptions.

🔹 Basic Syntax of try-except


python
CopyEdit
try:
# Code that may raise an exception
except ExceptionType:
# Code to handle the exception

🔹 Example 1: Handling ZeroDivisionError


python
CopyEdit
try:
x = 5 / 0 # This will cause a ZeroDivisionError
except ZeroDivisionError:
print("Cannot divide by zero!")

✅ Output:

csharp
CopyEdit
Cannot divide by zero!

🔹 Example 2: Handling Multiple Exceptions


python
CopyEdit
try:
num = int(input("Enter a number: ")) # User might enter non-numeric data
result = 10 / num # Might cause ZeroDivisionError
except ValueError:
print("Invalid input! Please enter a number.")
except ZeroDivisionError:
print("Cannot divide by zero.")

✅ Possible Outputs:

css
CopyEdit
Invalid input! Please enter a number. # If input is 'abc'
csharp
CopyEdit
Cannot divide by zero. # If input is 0

🔹 Example 3: Using else and finally

 else executes if no exceptions occur.


 finally always executes, whether an exception occurs or not.

python
CopyEdit
try:
num = int(input("Enter a number: "))
result = 10 / num
except ZeroDivisionError:
print("You cannot divide by zero!")
except ValueError:
print("Invalid input! Please enter a number.")
else:
print(f"Result: {result}") # Executes only if no error occurs
finally:
print("Execution completed.") # Always executes

✅ Possible Outputs:

yaml
CopyEdit
Enter a number: 2
Result: 5.0
Execution completed.
csharp
CopyEdit
Enter a number: 0
You cannot divide by zero!
Execution completed.
🔹 Raising Custom Exceptions using raise

You can manually raise exceptions using raise.

python
CopyEdit
try:
age = int(input("Enter your age: "))
if age < 0:
raise ValueError("Age cannot be negative!")
except ValueError as e:
print(f"Error: {e}")

✅ Output:

yaml
CopyEdit
Enter your age: -5
Error: Age cannot be negative!

🔹 Best Practices for Exception Handling

✅ Use specific exceptions (ValueError, IndexError) instead of a general except:


✅ Avoid catching all exceptions using except Exception:, unless necessary
✅ Use finally for cleanup (e.g., closing files or database connections)
✅ Use logging instead of print() in production
1. Python Installation & Setup:
o Install Anaconda and set up a Jupyter Notebook environment.
o Create a Python environment in Anaconda and install a new package (e.g.,
NumPy).
2. Basic Syntax: Variables, Data Types (int, float, str, bool):
o Create a program that takes a user’s name and age, and prints a greeting message
including their age.
o Write a program that stores a float and an integer in variables, adds them together,
and prints the result.
3. Operators: Arithmetic, Logical, Comparison, Assignment:
o Write a program to calculate the area of a rectangle using the formula: area =
length * width.
o Create a program that checks if a number is divisible by both 3 and 5 using logical
operators.
4. Control Flow: Conditional Statements (if-else, nested if):
o Write a program that takes a user's age and checks if they are eligible to vote (age
>= 18).
o Create a program that accepts a number and checks if it's positive, negative, or
zero.
5. Loops: for, while, break, continue:
o Write a program to print all even numbers between 1 and 50 using a for loop.
o Create a program that calculates the sum of numbers entered by the user until they
input 0 (using a while loop).
6. Functions: Defining, Calling, Arguments, Return Statements:
o Write a function that takes two numbers and returns their sum.
o Write a function to check if a number is prime or not.
7. Exception Handling: try-except-finally:
o Write a program that divides two numbers entered by the user, handling any
division by zero error.
o Write a program that takes user input for a number and prints the square of that
number, handling invalid input (e.g., letters instead of numbers).
1. Python Installation & Setup:
o Create a project in VS Code and configure the environment to run Python scripts.
o Set up Jupyter Notebook to use external Python packages, such as Pandas and
Matplotlib.
2. Basic Syntax: Variables, Data Types (int, float, str, bool):
o Write a program that accepts a user's name, age, and height, and then prints the
details in a formatted message.
o Create a program that converts kilometers to miles and outputs the result with a
message.
3. Operators: Arithmetic, Logical, Comparison, Assignment:
o Write a program that compares two numbers and prints the largest of the two.
o Create a program that accepts the number of hours worked and hourly wage, then
calculates the weekly salary.
4. Control Flow: Conditional Statements (if-else, nested if):
o Write a program that checks if a number is between 10 and 50 (inclusive).
o Create a program that assigns a letter grade (A, B, C, D, F) based on the score
entered by the user.
5. Loops: for, while, break, continue:
o Write a program to print the Fibonacci series up to the 20th term using a for loop.
o Create a program to count the number of vowels in a string entered by the user.
6. Functions: Defining, Calling, Arguments, Return Statements:
o Write a function that accepts a string and returns the string in reverse order.
o Create a function that calculates the factorial of a number using recursion.
7. Exception Handling: try-except-finally:
o Write a program to handle invalid date formats entered by the user and print a
friendly error message.
o Implement a program that reads from a file and handles possible file-related
exceptions (e.g., file not found).

1. Python Installation & Setup:


o Set up a Python virtual environment and use pip to install third-party libraries for
a data science project.
o Set up a project in VS Code that uses different Python versions for different
environments.
2. Basic Syntax: Variables, Data Types (int, float, str, bool):
o Write a program that simulates a banking system, with multiple accounts (using
dictionaries) and basic operations like deposit and withdrawal.
o Create a program that converts a string representing a number into an integer or
float, handling invalid inputs.
3. Operators: Arithmetic, Logical, Comparison, Assignment:
o Write a program that determines whether a year is a leap year using logical and
comparison operators.
o Create a program that takes two dates as input and calculates the difference in
days between them.
4. Control Flow: Conditional Statements (if-else, nested if):
o Implement a program that simulates a traffic light system (red, yellow, green)
using nested if statements.
o Create a program that checks the validity of a password based on rules like length,
special characters, and digits.
5. Loops: for, while, break, continue:
o Write a program to find the first 100 prime numbers using a for loop.
o Create a program that calculates the GCD (Greatest Common Divisor) of two
numbers using a while loop.
6. Functions: Defining, Calling, Arguments, Return Statements:
o Write a function that takes a list of numbers and returns the sum of the squares of
all even numbers in the list.
o Implement a function to solve the Towers of Hanoi problem using recursion.
7. Exception Handling: try-except-finally:
o Write a program that handles multiple exceptions (e.g., ZeroDivisionError,
ValueError, FileNotFoundError) for a given set of user inputs and file operations.
o Implement a custom exception that handles invalid input for a user’s age and
raises an error when the age is out of the valid range.
8. � � Practice Tasks
✅ Write a function to check if a number is prime
✅ Implement a simple calculator program
✅ Build a BMI calculator

Tips for Practicing:

 Start with beginner tasks and gradually move to intermediate and advanced tasks as
you get comfortable with the concepts.
 Practice debugging your code when exceptions or errors occur.
 Try to modify existing tasks to add more complexity (e.g., adding new conditions or
operations).
 Use external libraries or modules for advanced tasks to boost your understanding.

You might also like