Python coding
53 subscribers
24 files
11 links
​A technical hub dedicated to Python programming, web development, and software engineering. Learn core syntax, build full-stack projects, and master backend development.
Download Telegram
Python coding
🐍 Python Tip #7: The enumerate() Function When looping through a list, you sometimes need both the index and the value. Instead of manually tracking the index, Python provides the enumerate() function. --- Without enumerate() fruits = ["Apple", "Banana"…
⚡ Python Tip #8: The sorted() Function

The sorted() function returns a new sorted list without modifying the original one.

---

Basic Example

numbers = [5, 2, 8, 1, 9]

result = sorted(numbers)

print(result)

Output:

[1, 2, 5, 8, 9]

The original list remains unchanged.

---

Sorting in Descending Order

Use the reverse=True parameter.

numbers = [5, 2, 8, 1, 9]

result = sorted(numbers, reverse=True)

print(result)

Output:

[9, 8, 5, 2, 1]

---

Sorting Strings

fruits = ["Orange", "Apple", "Banana", "Mango"]

print(sorted(fruits))

Output:

['Apple', 'Banana', 'Mango', 'Orange']

---

Difference Between sorted() and sort()

sorted()

numbers = [3, 1, 2]

new_numbers = sorted(numbers)

print(numbers)
print(new_numbers)

Output:

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

---

`list.sort()

``
python
numbers = [3, 1, 2]

numbers.sort()

print(numbers)

Output:

python
[1, 2, 3]

Unlike `sorted()`, the `sort()` method modifies the original list.

---

Why use `sorted()`?

✓ Keeps the original data unchanged
✓ Easy to sort numbers and strings
✓ Supports ascending and descending order
✓ Commonly used in data processing and reporting

---

Challenge:

Given the list:

python
scores = [88, 95, 72, 100, 67]
`

1. Print the scores in ascending order.
2. Print the scores in descending order.
3. Verify that the original list remains unchanged after using `sorted()`.
Python coding
⚡ Python Tip #8: The sorted() Function The sorted() function returns a new sorted list without modifying the original one. --- Basic Example numbers = [5, 2, 8, 1, 9] result = sorted(numbers) print(result) Output: [1, 2, 5, 8, 9] The original list remains…
💡 Python Tip #9: Lambda Functions

A lambda function is a small anonymous function that can have any number of arguments but only one expression.

Lambda functions are useful when you need a simple function for a short period of time.

---

Basic Syntax

lambda arguments: expression

---

Example

Instead of writing:

def square(x):
return x ** 2

print(square(5))

You can write:

square = lambda x: x ** 2

print(square(5))

Output:

25

---

Multiple Arguments

Lambda functions can accept multiple arguments.

Example:

multiply = lambda a, b: a * b

print(multiply(6, 4))

Output:

24

---

Using lambda with sorted()

You can sort complex data using a custom key.

Example:

students = [
("Ali", 85),
("Sara", 95),
("John", 78)
]

result = sorted(
students,
key=lambda student: student[1]
)

print(result)

Output:

[('John', 78), ('Ali', 85), ('Sara', 95)]

---

Why use Lambda Functions?

✓ Write short functions quickly
✓ Useful with sorted(), map(), and filter()
✓ Makes code more concise
✓ Commonly used in data analysis and automation

---

Challenge:

Using a lambda function, create a function that returns the cube of a number.

Example:

cube = lambda x: x ** 3

print(cube(4))

Expected Output:

64
Python coding
💡 Python Tip #9: Lambda Functions A lambda function is a small anonymous function that can have any number of arguments but only one expression. Lambda functions are useful when you need a simple function for a short period of time. --- Basic Syntax lambda…
🚀 Python Tip #10: The collections.Counter Class

Counting how many times items appear in a list is a common task.

Instead of writing loops manually, Python provides the Counter class from the collections module.

---

Importing Counter

from collections import Counter

---

Basic Example

from collections import Counter

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

count = Counter(fruits)

print(count)

Output:

Counter({
'apple': 3,
'banana': 2,
'orange': 1
})

---

Counting Characters

from collections import Counter

text = "programming"

count = Counter(text)

print(count)

Output:

Counter({
'g': 2,
'r': 2,
'm': 2,
'p': 1,
'o': 1,
'a': 1,
'i': 1,
'n': 1
})

---

Finding the Most Common Items

Use the most_common() method.

Example:

from collections import Counter

votes = [
"Python",
"Java",
"Python",
"C++",
"Python",
"Java"
]

count = Counter(votes)

print(count.most_common(1))

Output:

[('Python', 3)]

---

Why use Counter?

✓ Count items with a single line of code
✓ Find the most common elements quickly
✓ Useful for text analysis and data processing
✓ Frequently used in Data Science and Machine Learning

---

Challenge:

Given the following list:

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

1. Count how many times each number appears.
2. Print the most common number.
3. Which number appears exactly once?
Python coding
🚀 Python Tip #10: The collections.Counter Class Counting how many times items appear in a list is a common task. Instead of writing loops manually, Python provides the Counter class from the collections module. --- Importing Counter from collections import…
🔥 Python Tip #11: The setdefault() Dictionary Method

When working with dictionaries, you may need to access a key that doesn't exist.

Instead of checking if the key exists first, Python provides the setdefault() method.

---

Basic Example

student = {
"name": "Ahmed",
"age": 18
}

print(student.setdefault("age", 20))

Output:

18

Since `"age" already exists, its value remains unchanged.

---

Adding a New Key

If the key does not exist,
setdefault() creates it using the default value.

Example:

``
python
student = {
"name": "Ahmed"
}

student.setdefault("country", "Ethiopia")

print(student)

Output:

python
{
'name': 'Ahmed',
'country': 'Ethiopia'
}

---

Without `setdefault()`

python
if "country" not in student:
student["country"] = "Ethiopia"

---

With `setdefault()`

python
student.setdefault("country", "Ethiopia")

Both produce the same result, but `setdefault()` is shorter and cleaner.

---

Practical Example

Count words without worrying about missing keys.

python
words = ["apple", "banana", "apple"]

counts = {}

for word in words:
counts.setdefault(word, 0)
counts[word] += 1

print(counts)

Output:

python
{
'apple': 2,
'banana': 1
}

---

Why use `setdefault()`?

✓ Avoids `KeyError`
✓ Reduces repetitive code
✓ Automatically creates missing keys
✓ Useful when counting, grouping, or organizing data

---

Challenge:

Given the list:

python
cities = [
"Addis Ababa",
"Adama",
"Addis Ababa",
"Hawassa",
"Adama"
]
`

Use `setdefault()` to count how many times each city appears.
Python coding
🔥 Python Tip #11: The setdefault() Dictionary Method When working with dictionaries, you may need to access a key that doesn't exist. Instead of checking if the key exists first, Python provides the setdefault() method. --- Basic Example student = { …
🐍 Python Tip #12: The pathlib Module

Working with files and folders is a common task in Python.

Instead of using traditional string paths, Python provides the pathlib module, which offers a cleaner and more object-oriented approach.

---

Importing Path

from pathlib import Path

---

Creating a Path

from pathlib import Path

file = Path("notes.txt")

print(file)

Output:

notes.txt

---

Checking if a File Exists

from pathlib import Path

file = Path("notes.txt")

print(file.exists())

Output:

True

or

```python
False

depending on whether the file exists.

---

Getting File Information

python
from pathlib import Path

file = Path("report.pdf")

print(file.name)
print(file.stem)
print(file.suffix)

Output:

python
report.pdf
report
.pdf

---

Creating a Folder

python
from pathlib import Path

folder = Path("Projects")

folder.mkdir(exist_ok=True)

The `exist_ok=True` argument prevents an error if the folder already exists.

---

Joining Paths

Instead of writing:

python
path = "Projects/" + "Python/" + "main.py"

Use:

python
from pathlib import Path

path = Path("Projects") / "Python" / "main.py"

print(path)

Output:

python
Projects/Python/main.py

---

Why use `pathlib`?

✓ Cleaner and easier to read
✓ Works across Windows, Linux, and macOS
✓ Object-oriented design
✓ Recommended for modern Python projects

---

Challenge:

Create a program that:

1. Creates a folder named:

python
Python_Practice

2. Checks whether a file named:

python
notes.txt

exists inside that folder.

3. Prints:

text
File found

or

text
File not found
`

based on the result.
🤔1
Python coding
🐍 Python Tip #12: The pathlib Module Working with files and folders is a common task in Python. Instead of using traditional string paths, Python provides the pathlib module, which offers a cleaner and more object-oriented approach. --- Importing Path…
🧪 Python Tip #13: Using MagicMock for Testing

When writing unit tests, you don't always want to call real databases, APIs, or external services.

Instead, you can use MagicMock from Python's unittest.mock module to simulate their behavior.

---

Importing MagicMock

from unittest.mock import MagicMock

---

Why Use MagicMock?

Imagine you have a function that connects to a database.

In a real application, this function might:

- Take several seconds to execute
- Require an internet connection
- Access a real database
- Return different results each time

During testing, this is slow and unreliable.

---

Without MagicMock

def get_user_from_db(user_id):
# Slow database query
pass

user = get_user_from_db(1)

print(user)

This would execute the real database logic.

---

With MagicMock

from unittest.mock import MagicMock

def get_user_from_db(user_id):
# Slow database query
pass

get_user_from_db = MagicMock(
return_value={
"id": 1,
"name": "John Doe"
}
)

user = get_user_from_db(1)

print(user)

Output:

{'id': 1, 'name': 'John Doe'}

---

How It Works

MagicMock(return_value=...)

Creates a fake version of the function.

Whenever the function is called, it immediately returns the specified value instead of executing the original code.

---

Why use MagicMock?

✓ Makes tests run much faster
✓ No need for a real database or API
✓ Produces predictable results
✓ Essential for professional unit testing

---

Challenge:

Create a MagicMock that simulates a weather API and returns:

{
"city": "Addis Ababa",
"temperature": 22,
"condition": "Sunny"
}

Then print the returned dictionary.
Python coding
🧪 Python Tip #13: Using MagicMock for Testing When writing unit tests, you don't always want to call real databases, APIs, or external services. Instead, you can use MagicMock from Python's unittest.mock module to simulate their behavior. --- Importing…
⚡ Python Tip #14: The Walrus Operator (:=)

Introduced in Python 3.8, the walrus operator allows you to assign a value to a variable as part of an expression.

This can make your code shorter and avoid repeating calculations.

---

Without the Walrus Operator

name = input("Enter your name: ")

while name != "exit":
print(f"Hello, {name}!")
name = input("Enter your name: ")

---

With the Walrus Operator

while (name := input("Enter your name: ")) != "exit":
print(f"Hello, {name}!")

The program behaves exactly the same but requires fewer lines of code.

---

Another Example

Without the walrus operator:

numbers = [5, 8, 12, 20]

length = len(numbers)

if length > 3:
print(f"The list contains {length} items.")

---

With the walrus operator:

numbers = [5, 8, 12, 20]

if (length := len(numbers)) > 3:
print(f"The list contains {length} items.")

---

When Should You Use It?

The walrus operator is useful when:

- A value is needed more than once
- You want to avoid repeating a function call
- You want cleaner and more efficient code

However, don't overuse it. Sometimes a normal assignment is easier to read.

---

Why use the Walrus Operator?

✓ Reduces repeated calculations
✓ Makes some loops cleaner
✓ Can improve performance in certain situations
✓ Useful in data processing and file handling

---

Challenge:

Using the walrus operator, write a program that repeatedly asks the user to enter a number until they type:

quit

Print each number entered before the program exits.
Python coding
⚡ Python Tip #14: The Walrus Operator (:=) Introduced in Python 3.8, the walrus operator allows you to assign a value to a variable as part of an expression. This can make your code shorter and avoid repeating calculations. --- Without the Walrus Operator…
💡 Python Tip #15: The is vs == Operators

Many beginners confuse is and ==, but they have different purposes.

---

Using ==

The == operator checks whether two values are equal.

Example:

a = [1, 2, 3]
b = [1, 2, 3]

print(a == b)

Output:

True

Both lists contain the same values.

---

Using is

The is operator checks whether two variables refer to the exact same object in memory.

Example:

a = [1, 2, 3]
b = [1, 2, 3]

print(a is b)

Output:

False

Although the values are equal, they are stored as different objects.

---

Same Object Example

a = [1, 2, 3]
b = a

print(a is b)
print(a == b)

Output:

True
True

Both variables point to the same object.

---

Checking for None

The recommended way to check for None is with is.

Correct:

name = None

if name is None:
print("No name provided")

Avoid:

if name == None:
print("No name provided")

Using `is None is the Pythonic approach.

---

Why does this matter?

✓ Prevents subtle bugs
✓ Improves code readability
✓ Follows Python best practices
✓ Commonly used in professional Python projects

---

Challenge:

What will this code print?

``
python
x = [10, 20]
y = x
z = [10, 20]

print(x == z)
print(x is z)
print(x is y)
`

Try to predict the output before running the code.
Python coding
💡 Python Tip #15: The is vs == Operators Many beginners confuse is and ==, but they have different purposes. --- Using == The == operator checks whether two values are equal. Example: a = [1, 2, 3] b = [1, 2, 3] print(a == b) Output: True Both lists…
🔥 Python Tip #16: The with Statement

When working with files, it's important to close them after you're done.

Python's with statement automatically handles this for you.

---

Without with

file = open("notes.txt", "r")

content = file.read()

print(content)

file.close()

If an error occurs before file.close(), the file may remain open.

---

With with

with open("notes.txt", "r") as file:
content = file.read()
print(content)

Once the block ends, Python automatically closes the file.

---

Writing to a File

with open("hello.txt", "w") as file:
file.write("Hello, Python!")

This creates the file if it doesn't exist, or overwrites it if it does.

---

Appending to a File

Use "a" mode to add new content without deleting the existing content.

with open("hello.txt", "a") as file:
file.write("\nWelcome back!")

---

Why use the with statement?

✓ Automatically closes files
✓ Prevents resource leaks
✓ Cleaner and more readable code
✓ Recommended for all file operations

---

Challenge:

Create a program that:

1. Creates a file named:

tasks.txt

2. Writes three tasks into the file.

3. Opens the same file and prints all its contents using the with statement.
Python coding
🔥 Python Tip #16: The with Statement When working with files, it's important to close them after you're done. Python's with statement automatically handles this for you. --- Without with file = open("notes.txt", "r") content = file.read() print(content)…
🎯 Python Tip #17: The match-case Statement

Introduced in Python 3.10, the match-case statement provides a cleaner alternative to long chains of if...elif...else.

It is similar to the "switch" statement found in many other programming languages.

---

Without match-case

day = 3

if day == 1:
print("Monday")
elif day == 2:
print("Tuesday")
elif day == 3:
print("Wednesday")
else:
print("Invalid day")

---

With match-case

day = 3

match day:
case 1:
print("Monday")
case 2:
print("Tuesday")
case 3:
print("Wednesday")
case _:
print("Invalid day")

Output:

Wednesday

---

Matching Strings

command = "start"

match command:
case "start":
print("Program started")
case "stop":
print("Program stopped")
case "restart":
print("Program restarted")
case _:
print("Unknown command")

---

The Wildcard _

The underscore (_) acts as the default case.

Example:

case _:
print("No match found")

It is equivalent to the else statement.

---

Why use match-case?

✓ Cleaner than multiple if...elif statements
✓ Easier to read and maintain
✓ Perfect for menus and command handling
✓ Great for pattern matching in modern Python

> Note: match-case is available only in Python 3.10 and later.

---

Challenge:

Write a program that asks the user to enter one of these commands:

add
remove
update
list

Use `match-case to print the corresponding action. If the command is not recognized, print:

``
text
Invalid command
`
Python coding
🎯 Python Tip #17: The match-case Statement Introduced in Python 3.10, the match-case statement provides a cleaner alternative to long chains of if...elif...else. It is similar to the "switch" statement found in many other programming languages. --- Without…
🐍 Python Tip #18: The for...else Statement

Most Python programmers know about if...else, but fewer know that loops can also have an else block.

The else block executes only if the loop finishes normally (without encountering a break).

---

Basic Example

for i in range(5):
print(i)
else:
print("Loop completed successfully!")

Output:

0
1
2
3
4
Loop completed successfully!

---

Using break

If the loop is interrupted with break, the else block will not execute.

Example:

for i in range(5):
if i == 3:
break
print(i)
else:
print("Loop completed successfully!")

Output:

0
1
2

Notice that "Loop completed successfully!" is never printed.

---

Searching Example

The for...else statement is especially useful when searching for an item.

numbers = [10, 20, 30, 40]

target = 25

for number in numbers:
if number == target:
print("Number found!")
break
else:
print("Number not found!")

Output:

Number not found!

---

When is for...else Useful?

✓ Searching for an item
✓ Validating data
✓ Avoiding extra boolean variables
✓ Writing cleaner search algorithms

---

Challenge:

Given the following list:

students = ["Ali", "Sara", "John", "Mariam"]

Search for:

"Ahmed"

If the student exists, print:

Student found!

Otherwise, use the else block to print:

Student not found!
Python coding
🐍 Python Tip #18: The for...else Statement Most Python programmers know about if...else, but fewer know that loops can also have an else block. The else block executes only if the loop finishes normally (without encountering a break). --- Basic Example…
💡 Python Tip #19: The dict.get() Method

When accessing dictionary values, using square brackets ([]) can raise an error if the key doesn't exist.

Python provides the get() method as a safer alternative.

---

Using Square Brackets

student = {
"name": "Ali",
"age": 18
}

print(student["name"])

Output:

Ali

---

What Happens if the Key Doesn't Exist?

student = {
"name": "Ali"
}

print(student["country"])

Output:

KeyError: 'country'

The program stops because the key doesn't exist.

---

Using get()

student = {
"name": "Ali"
}

print(student.get("country"))

Output:

None

Instead of raising an error, get() returns None.

---

Providing a Default Value

You can specify a default value if the key is missing.

student = {
"name": "Ali"
}

print(student.get("country", "Unknown"))

Output:

Unknown

---

Practical Example

settings = {
"theme": "Dark"
}

theme = settings.get("theme", "Light")
language = settings.get("language", "English")

print(theme)
print(language)

Output:

Dark
English

---

Why use get()?

✓ Prevents KeyError
✓ Makes your code more reliable
✓ Allows default values
✓ Commonly used when working with JSON data and APIs

---

Challenge:

Given the dictionary:

book = {
"title": "Python Basics",
"author": "Yehya"
}

Use the get() method to print:

- The value of "title"
- The value of "price" (use "Not Available" as the default value)
Python coding
💡 Python Tip #19: The dict.get() Method When accessing dictionary values, using square brackets ([]) can raise an error if the key doesn't exist. Python provides the get() method as a safer alternative. --- Using Square Brackets student = { "name":…
🚀 Python Tip #20: The collections.defaultdict Class

When working with dictionaries, you often need to check whether a key already exists before using it.

Python's defaultdict automatically creates missing keys with a default value.

---

Importing defaultdict

from collections import defaultdict

---

Without defaultdict

scores = {}

for name in ["Ali", "Sara", "Ali"]:
if name not in scores:
scores[name] = 0
scores[name] += 1

print(scores)

Output:

{'Ali': 2, 'Sara': 1}

---

With defaultdict

from collections import defaultdict

scores = defaultdict(int)

for name in ["Ali", "Sara", "Ali"]:
scores[name] += 1

print(dict(scores))

Output:

{'Ali': 2, 'Sara': 1}

---

Grouping Data

defaultdict is also useful for grouping values.

Example:

from collections import defaultdict

students = defaultdict(list)

students["Grade A"].append("Ali")
students["Grade A"].append("Sara")
students["Grade B"].append("John")

print(dict(students))

Output:

{
'Grade A': ['Ali', 'Sara'],
'Grade B': ['John']
}

---

Common Default Types

defaultdict(int)     # Default value: 0
defaultdict(float) # Default value: 0.0
defaultdict(str) # Default value: ""
defaultdict(list) # Default value: []
defaultdict(set) # Default value: set()

---

Why use defaultdict?

✓ Eliminates repetitive key checks
✓ Makes code cleaner and shorter
✓ Perfect for counting and grouping data
✓ Frequently used in Data Science and competitive programming

---

Challenge:

Given the following list:

animals = [
("Mammal", "Lion"),
("Bird", "Eagle"),
("Mammal", "Tiger"),
("Bird", "Parrot"),
("Fish", "Salmon")
]

Use `defaultdict(list) to group the animals by their category.

Expected Output:

``
python
{
'Mammal': ['Lion', 'Tiger'],
'Bird': ['Eagle', 'Parrot'],
'Fish': ['Salmon']
}
`
⚡ Python Tip #21: The functools.lru_cache Decorator

Some functions perform the same calculations repeatedly, which can slow down your program.

Python provides the lru_cache decorator to automatically remember previous results and reuse them.

---

Importing lru_cache

from functools import lru_cache

---

Without lru_cache

def fibonacci(n):
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)

print(fibonacci(35))

This works, but it recalculates the same values many times, making it slow.

---

With lru_cache

from functools import lru_cache

@lru_cache(maxsize=None)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)

print(fibonacci(35))

The result is the same, but the function runs much faster because previous results are stored in memory.

---

How It Works

@lru_cache(maxsize=None)

- `@lru_cache enables caching.
-
maxsize=None means there is no limit on the number of cached results.

---

Another Example

``
python
from functools import lru_cache

@lru_cache(maxsize=None)
def square(n):
print("Calculating...")
return n ** 2

print(square(5))
print(square(5))

Output:

python
Calculating...
25
25
`

Notice that `"Calculating..."` is printed only once because the second call uses the cached result.

---

Why use `lru_cache`?

✓ Speeds up repeated function calls
✓ Avoids unnecessary calculations
✓ Simple to use with a single decorator
✓ Commonly used in recursion, dynamic programming, and optimization

---

Challenge:

Create a recursive function that calculates the factorial of a number and use `@lru_cache(maxsize=None)` to cache its results.

Test your function by calling it multiple times with the same input and observe how caching improves efficiency.
Python coding
⚡ Python Tip #21: The functools.lru_cache Decorator Some functions perform the same calculations repeatedly, which can slow down your program. Python provides the lru_cache decorator to automatically remember previous results and reuse them. --- Importing…
🐍 Python Tip #22: The dataclass Decorator

When creating classes that mainly store data, Python provides the @dataclass decorator to reduce boilerplate code.

It automatically generates methods like __init__(), __repr__(), and __eq__().

---

Importing dataclass

from dataclasses import dataclass

---

Without @dataclass

class Student:
def __init__(self, name, age, grade):
self.name = name
self.age = age
self.grade = grade

student = Student("Ali", 18, "A")

print(student.name)
print(student.age)
print(student.grade)

---

With @dataclass

from dataclasses import dataclass

@dataclass
class Student:
name: str
age: int
grade: str

student = Student("Ali", 18, "A")

print(student)

Output:

Student(name='Ali', age=18, grade='A')

---

Comparing Objects

from dataclasses import dataclass

@dataclass
class Point:
x: int
y: int

p1 = Point(2, 3)
p2 = Point(2, 3)

print(p1 == p2)

Output:

True

Without @dataclass, these objects would normally not be considered equal unless eqplemented __eq__() yourself.

---

Using Default Values

from dataclasses import dataclass

@dataclass
class User:
username: str
active: bool = True

user = User("Yehya")

print(user)

Output:

User(username='Yehya', active=True)

---

Why use @dataclass?

✓ Less boilerplate code
✓ Automainitcreates __init__() and other methods
✓ Improves readability
✓ Ideal for configuration objects, API responses, and data models

---

Challenge:

Create a Book dataclass with the following fields:

title: str
author: str
pages: int
price: float

Then create an object and print it.
Python coding
🐍 Python Tip #22: The dataclass Decorator When creating classes that mainly store data, Python provides the @dataclass decorator to reduce boilerplate code. It automatically generates methods like __init__(), __repr__(), and __eq__(). --- Importing dataclass…
🚀 Python Tip #23: The itertools.product() Function

The product() function from Python's itertools module returns the Cartesian product of two or more iterables.

It is useful for generating all possible combinations.

---

Importing product

from itertools import product

---

Basic Example

from itertools import product

colors = ["Red", "Blue"]
sizes = ["S", "M", "L"]

result = product(colors, sizes)

for item in result:
print(item)

Output:

('Red', 'S')
('Red', 'M')
('Red', 'L')
('Blue', 'S')
('Blue', 'M')
('Blue', 'L')

---

Converting to a List

If you want to store all combinations:

from itertools import product

letters = ["A", "B"]
numbers = [1, 2, 3]

result = list(product(letters, numbers))

print(result)

Output:

[('A', 1), ('A', 2), ('A', 3), ('B', 1), ('B', 2), ('B', 3)]

---

Repeating an Iterable

Use the repeat parameter to generate combinations from the same iterable.

from itertools import product

result = list(product([0, 1], repeat=3))

print(result)

Output:

[(0, 0, 0),
(0, 0, 1),
(0, 1, 0),
(0, 1, 1),
(1, 0, 0),
(1, 0, 1),
(1, 1, 0),
(1, 1, 1)]

---

Why use itertools.product()?

✓ Generates every possible combination automatically
✓ Eliminates nested loops
✓ Useful for brute-force algorithms and testing
✓ Commonly used in Data Science, AI, and combinatorial problems

---

Challenge:

Given the following lists:

shirts = ["Black", "White"]
pants = ["Jeans", "Shorts"]
shoes = ["Sneakers", "Boots"]

Use `itertools.product()` to generate every possible outfit combination.
Python coding
🚀 Python Tip #23: The itertools.product() Function The product() function from Python's itertools module returns the Cartesian product of two or more iterables. It is useful for generating all possible combinations. --- Importing product from itertools…
🚀 Python Tip #24: The itertools.groupby() Function

The groupby() function from Python's itertools module groups consecutive items that have the same key.

It is useful for organizing and summarizing data.

---

Importing groupby

from itertools import groupby

---

Basic Example

from itertools import groupby

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

for key, group in groupby(numbers):
print(key, list(group))

Output:

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

---

Grouping Strings

from itertools import groupby

text = "aaabbbbccdaa"

for letter, group in groupby(text):
print(letter, len(list(group)))

Output:

a 3
b 4
c 2
d 1
a 2

Notice that the last "a" forms a new group because groupby() only groups consecutive items.

---

Grouping Objects

from itertools import groupby

students = [
("Ali", "A"),
("Sara", "A"),
("John", "B"),
("Mariam", "B")
]

for grade, group in groupby(students, key=lambda x: x[1]):
print(grade, list(group))

Output:

A [('Ali', 'A'), ('Sara', 'A')]
B [('John', 'B'), ('Mariam', 'B')]

---

Important Note

If your data is not already sorted by the grouping key, sort it first.

students = sorted(students, key=lambda x: x[1])

This ensures that all items with the same key appear together.

---

Why use groupby()?

✓ Groups consecutive data efficiently
✓ Useful for reports and summaries
✓ Works well with sorted datasets
✓ Commonly used in data analysis and log processing

---

Challenge:

Given the following list:

words = [
"apple",
"ant",
"banana",
"ball",
"cat",
"car"
]

Sort the list and use groupby() to group the words by their first letter.

Expected Output:

a ['ant', 'apple']
b ['ball', 'banana']
c ['car', 'cat']
Python coding
🚀 Python Tip #24: The itertools.groupby() Function The groupby() function from Python's itertools module groups consecutive items that have the same key. It is useful for organizing and summarizing data. --- Importing groupby from itertools import groupby…
⚡ Python Tip #25: The timeit Module

When optimizing your code, don't guess which approach is faster—measure it.

Python's timeit module helps you accurately measure the execution time of small code snippets.

---

Importing timeit

import timeit

---

Basic Example

import timeit

execution_time = timeit.timeit(
"sum(range(100))",
number=10000
)

print(execution_time)

Output:

0.0...

(The exact time will vary depending on your computer.)

---

Comparing Two Approaches

Method 1

import timeit

list_time = timeit.timeit(
"[x for x in range(1000)]",
number=10000
)

print(list_time)

Method 2

import timeit

loop_time = timeit.timeit(
"""
numbers = []
for x in range(1000):
numbers.append(x)
""",
number=10000
)

print(loop_time)

By comparing the results, you can determine which approach is faster.

---

Using a Function

import timeit

def square():
return [x ** 2 for x in range(1000)]

print(timeit.timeit(square, number=1000))

---

Why use timeit?

✓ Measures execution time accurately
✓ Helps optimize performance
✓ Ideal for benchmarking different solutions
✓ Widely used by professional Python developers

---

Challenge:

Compare the execution time of these two methods for creating a list of numbers from 0 to 9999:

Method 1:

[x for x in range(10000)]

Method 2:

numbers = []

for i in range(10000):
numbers.append(i)

Use the timeit module to determine which method is faster on your machine.
Python coding
⚡ Python Tip #25: The timeit Module When optimizing your code, don't guess which approach is faster—measure it. Python's timeit module helps you accurately measure the execution time of small code snippets. --- Importing timeit import timeit --- Basic…
🐍 Python Tip #26: The contextlib.suppress() Context Manager

Sometimes you expect an exception to occur and want to ignore it safely.

Python's contextlib.suppress() provides a clean way to suppress specific exceptions without using a try...except block.

---

Importing suppress

from contextlib import suppress

---

Without suppress()

try:
with open("data.txt") as file:
print(file.read())
except FileNotFoundError:
pass

This works, but it becomes repetitive if used frequently.

---

With suppress()

from contextlib import suppress

with suppress(FileNotFoundError):
with open("data.txt") as file:
print(file.read())

If `data.txt doesn't exist, no error is raised and the program continues.

---

Suppressing Multiple Exceptions

You can suppress more than one exception.

``
python
from contextlib import suppress

with suppress(FileNotFoundError, ZeroDivisionError):
print(10 / 0)

The program continues running without crashing.

---

When Should You Use It?

Use `suppress()` only when an exception is expected and safely ignorable.

Examples include:

- Removing a file that may not exist
- Opening an optional configuration file
- Handling optional resources

Avoid using it to hide unexpected errors, as this can make debugging difficult.

---

Why use `contextlib.suppress()`?

✓ Cleaner than empty `try...except` blocks
✓ Makes your code more readable
✓ Handles expected exceptions gracefully
✓ Useful in scripts, automation, and file management

---

Challenge:

Write a program that attempts to delete a file named:

python
temp.txt
`

Use `contextlib.suppress()` so that if the file does not exist, the program continues without raising an error.