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 #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.
Python coding
🐍 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. …
💡 Python Tip #27: The pathlib.Path.glob() Method

Searching for files manually can be tedious, especially in large directories.

Python's pathlib module provides the glob() method to easily find files using patterns.

---

Importing Path

from pathlib import Path

---

Finding All Python Files

from pathlib import Path

folder = Path(".")

for file in folder.glob("*.py"):
print(file)

Output:

main.py
app.py
utils.py

The `*.py pattern matches all files ending with .py.

---

Finding Text Files

``
python
from pathlib import Path

folder = Path("documents")

for file in folder.glob("*.txt"):
print(file.name)

This prints the names of all text files in the `documents` folder.

---

Searching Recursively

Use `rglob()` to search through all subfolders.

python
from pathlib import Path

folder = Path(".")

for file in folder.rglob("*.py"):
print(file)

This finds every Python file in the current directory and all of its subdirectories.

---

Common Patterns

python
*.py # All Python files
*.txt # All text files
*.jpg # All JPEG images
data_* # Files starting with "data_"
*.* # All files with an extension
`

---

Why use `glob()`?

✓ Easily search for files using patterns
✓ Eliminates manual file filtering
✓ Works across different operating systems
✓ Useful for automation, backups, and data processing

---

Challenge:

Write a program that searches the current directory for all PDF files.

Then print:

- The file name
- The file extension
- The full file path

using the `pathlib` module.
Python coding
💡 Python Tip #27: The pathlib.Path.glob() Method Searching for files manually can be tedious, especially in large directories. Python's pathlib module provides the glob() method to easily find files using patterns. --- Importing Path from pathlib import…
🚀 Python Tip #28: The collections.deque Class

Python lists are excellent for most tasks, but they become inefficient when adding or removing items from the beginning.

The deque (double-ended queue) from the collections module is designed for fast insertions and deletions from both ends.

---

Importing deque

from collections import deque

---

Creating a Deque

from collections import deque

queue = deque([1, 2, 3])

print(queue)

Output:

deque([1, 2, 3])

---

Adding Elements

Append to the right:

from collections import deque

queue = deque([1, 2, 3])

queue.append(4)

print(queue)

Output:

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

Append to the left:

queue.appendleft(0)

print(queue)

Output:

deque([0, 1, 2, 3, 4])

---

Removing Elements

Remove from the right:

queue.pop()

Remove from the left:

queue.popleft()

Example:

from collections import deque

queue = deque([1, 2, 3])

queue.popleft()

print(queue)

Output:

deque([2, 3])

---

Limiting the Size

A deque can have a maximum length.

from collections import deque

history = deque(maxlen=3)

history.append("Page 1")
history.append("Page 2")
history.append("Page 3")
history.append("Page 4")

print(history)

Output:

deque(['Page 2', 'Page 3', 'Page 4'])

The oldest item is automatically removed when the limit is exceeded.

---

Why use deque?

✓ Fast insertions and deletions from both ends
✓ More efficient than lists for queue operations
✓ Supports fixed-size queues with maxlen
✓ Commonly used in task scheduling, caching, and breadth-first search (BFS)

---

Challenge:

Create a deque with a maximum length of 5.

Then:

1. Add the numbers 1 through 7.
2. Print the deque.
3. Explain why the first two numbers are no longer present.
Python coding
🚀 Python Tip #28: The collections.deque Class Python lists are excellent for most tasks, but they become inefficient when adding or removing items from the beginning. The deque (double-ended queue) from the collections module is designed for fast insertions…
⚡ Python Tip #29: The collections.namedtuple Class

A namedtuple is like a regular tuple, but with named fields instead of numeric indexes.

It makes your code more readable and easier to understand.

---

Importing namedtuple

from collections import namedtuple

---

Creating a namedtuple

from collections import namedtuple

Student = namedtuple("Student", ["name", "age", "grade"])

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

print(student)

Output:

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

---

Accessing Values

You can access values using their field names.

from collections import namedtuple

Student = namedtuple("Student", ["name", "age", "grade"])

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

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

Output:

Ali
18
A

---

Using Indexes

A namedtuple is still a tuple, so indexing also works.

print(student[0])
print(student[1])

Output:

Ali
18

---

Converting to a Dictionary

Use the _asdict() method.

from collections import namedtuple

Car = namedtuple("Car", ["brand", "model", "year"])

car = Car("Toyota", "Corolla", 2024)

print(car._asdict())

Output:

{
'brand': 'Toyota',
'model': 'Corolla',
'year': 2024
}

---

Why use namedtuple?

✓ More readable than regular tuples
✓ Access values by name instead of index
✓ Lightweight and memory-efficient
✓ Commonly used for structured, immutable data

---

Challenge:

Create a Book namedtuple with the following fields:

title
author
pages

Create an object with your own values and print:

- The title
- The author
- The number of pages
- The dictionary representation using _asdict()
Python coding
⚡ Python Tip #29: The collections.namedtuple Class A namedtuple is like a regular tuple, but with named fields instead of numeric indexes. It makes your code more readable and easier to understand. --- Importing namedtuple from collections import namedtuple…
🐍 Python Tip #30: The collections.ChainMap Class

Sometimes you need to work with multiple dictionaries as if they were a single dictionary.

Python's ChainMap from the collections module allows you to do exactly that without merging the dictionaries.

---

Importing ChainMap

from collections import ChainMap

---

Basic Example

from collections import ChainMap

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

dict2 = {
"country": "Ethiopia",
"language": "English"
}

combined = ChainMap(dict1, dict2)

print(combined)

Output:

ChainMap({
'name': 'Ali',
'age': 18
}, {
'country': 'Ethiopia',
'language': 'English'
})

---

Accessing Values

You can access values just like a normal dictionary.

print(combined["name"])
print(combined["country"])

Output:

Ali
Ethiopia

---

Handling Duplicate Keys

If multiple dictionaries contain the same key, ChainMap uses the value from the first dictionary.

from collections import ChainMap

dict1 = {"language": "Python"}
dict2 = {"language": "Java"}

combined = ChainMap(dict1, dict2)

print(combined["language"])

Output:

Python

---

Updating Values

Changes affect only the first dictionary.

from collections import ChainMap

dict1 = {"x": 10}
dict2 = {"y": 20}

combined = ChainMap(dict1, dict2)

combined["x"] = 100

print(dict1)

Output:

{'x': 100}

---

Why use ChainMap?

✓ Combines multiple dictionaries without copying data
✓ Saves memory
✓ Access dictionaries as one mapping
✓ Useful for configuration settings and variable scopes

---

Challenge:

Given the following dictionaries:

default_settings = {
"theme": "Light",
"language": "English"
}

user_settings = {
"theme": "Dark"
}

Use `ChainMap to combine them.

Then print:

- The selected theme
- The selected language

Explain why the theme is
"Dark" even though both dictionaries contain a "theme"` key.
Python coding
🐍 Python Tip #30: The collections.ChainMap Class Sometimes you need to work with multiple dictionaries as if they were a single dictionary. Python's ChainMap from the collections module allows you to do exactly that without merging the dictionaries. --…
💡 Python Tip #31: The functools.partial() Function

Sometimes you repeatedly call a function with the same arguments.

Python's partial() function allows you to "freeze" some arguments, creating a new function with predefined values.

---

Importing partial

from functools import partial

---

Basic Example

from functools import partial

def power(base, exponent):
return base ** exponent

square = partial(power, exponent=2)

print(square(5))

Output:

25

The `square() function automatically uses 2 as the exponent.

---

Creating Multiple Functions

``
python
from functools import partial

def multiply(a, b):
return a * b

double = partial(multiply, b=2)
triple = partial(multiply, b=3)

print(double(10))
print(triple(10))

Output:

python
20
30

---

Using Positional Arguments

python
from functools import partial

def greet(greeting, name):
return f"{greeting}, {name}!"

say_hello = partial(greet, "Hello")

print(say_hello("Yehya"))

Output:

python
Hello, Yehya!

---

Why use `partial()`?

✓ Reduces repetitive code
✓ Creates specialized versions of existing functions
✓ Improves code readability
✓ Useful in GUI programming, web development, and callbacks

---

Challenge:

Create a function:

python
def calculate(price, tax):
return price + tax

Then use `partial()` to create a new function called:

python
add_vat

that always uses:

python
tax = 15

Finally, calculate the total price for:

python
price = 200
`
Python coding
💡 Python Tip #31: The functools.partial() Function Sometimes you repeatedly call a function with the same arguments. Python's partial() function allows you to "freeze" some arguments, creating a new function with predefined values. --- Importing partial…
🚀 Python Tip #32: The collections.OrderedDict Class

Although modern Python dictionaries preserve insertion order, the OrderedDict class provides additional features for working with ordered data.

It is available in the collections module.

---

Importing OrderedDict

from collections import OrderedDict

---

Creating an OrderedDict

from collections import OrderedDict

student = OrderedDict()

student["name"] = "Ali"
student["age"] = 18
student["grade"] = "A"

print(student)

Output:

OrderedDict([
('name', 'Ali'),
('age', 18),
('grade', 'A')
])

---

Moving an Item

You can move an existing key to the beginning or end of the dictionary.

from collections import OrderedDict

student = OrderedDict([
("name", "Ali"),
("age", 18),
("grade", "A")
])

student.move_to_end("name")

print(student)

Output:

OrderedDict([
('age', 18),
('grade', 'A'),
('name', 'Ali')
])

---

Removing the First or Last Item

The popitem() method removes items in order.

from collections import OrderedDict

student = OrderedDict([
("name", "Ali"),
("age", 18),
("grade", "A")
])

student.popitem(last=False)

print(student)

Output:

OrderedDict([
('age', 18),
('grade', 'A')
])

Using `last=False removes the first item.

---

When Should You Use
OrderedDict?

While the built-in
dict preserves insertion order in Python 3.7+, OrderedDict is still useful when you need methods like:

-
move_to_end()
-
popitem(last=False)

These features are not available with a regular dictionary.

---

Why use
OrderedDict?

✓ Maintains insertion order
✓ Easily reorder dictionary items
✓ Supports advanced ordering operations
✓ Useful for caches, queues, and ordered data processing

---

Challenge:

Create an
OrderedDict containing the following items:

``
python
{
"A": 10,
"B": 20,
"C": 30,
"D": 40
}
`

Then:

1. Move `"B"` to the end.
2. Remove the first item.
3. Print the final `OrderedDict`.
Python coding
🚀 Python Tip #32: The collections.OrderedDict Class Although modern Python dictionaries preserve insertion order, the OrderedDict class provides additional features for working with ordered data. It is available in the collections module. --- Importing…
🐍 Python Tip #33: The itertools.islice() Function

When working with large iterables, you may only need a portion of the data.

Python's itertools.islice() lets you slice any iterable without converting it into a list first.

---

Importing islice

from itertools import islice

---

Basic Example

from itertools import islice

numbers = range(1, 11)

result = list(islice(numbers, 5))

print(result)

Output:

[1, 2, 3, 4, 5]

---

Specifying a Start and Stop

from itertools import islice

numbers = range(1, 11)

result = list(islice(numbers, 2, 7))

print(result)

Output:

[3, 4, 5, 6, 7]

---

Using a Step

Just like normal slicing, you can specify a step value.

from itertools import islice

numbers = range(1, 21)

result = list(islice(numbers, 0, 20, 3))

print(result)

Output:

[1, 4, 7, 10, 13, 16, 19]

---

Why Use islice()?

Unlike normal list slicing, islice() works directly on iterators and generators without loading everything into memory.

Example:

from itertools import islice

squares = (x ** 2 for x in range(1000000))

print(list(islice(squares, 5)))

Output:

[0, 1, 4, 9, 16]

Only the required values are generated.

---

Why use itertools.islice()?

✓ Memory efficient
✓ Works with generators and iterators
✓ Supports start, stop, and step values
✓ Commonly used in data processing and large datasets

---

Challenge:

Create a generator that produces the numbers from 1 to 100.

Then use islice() to print only:

11, 12, 13, 14, 15

without converting the entire generator into a list.
Python coding
🐍 Python Tip #33: The itertools.islice() Function When working with large iterables, you may only need a portion of the data. Python's itertools.islice() lets you slice any iterable without converting it into a list first. --- Importing islice from itertools…
⚡ Python Tip #34: The itertools.chain() Function

The chain() function from Python's itertools module allows you to combine multiple iterables into a single iterator.

It is a memory-efficient alternative to concatenating lists.

---

Importing chain

from itertools import chain

---

Basic Example

from itertools import chain

list1 = [1, 2, 3]
list2 = [4, 5, 6]

result = chain(list1, list2)

print(list(result))

Output:

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

---

Combining Multiple Iterables

from itertools import chain

letters = ["A", "B"]
numbers = [1, 2]
symbols = ["@", "#"]

result = chain(letters, numbers, symbols)

print(list(result))

Output:

['A', 'B', 1, 2, '@', '#']

---

Using chain.from_iterable()

If your iterables are stored inside another iterable, use from_iterable().

from itertools import chain

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

result = chain.from_iterable(data)

print(list(result))

Output:

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

---

Why Use chain()?

Without chain():

list1 = [1, 2, 3]
list2 = [4, 5, 6]

result = list1 + list2

print(result)

With `chain():

``
python
from itertools import chain

result = chain(list1, list2)

print(list(result))

`chain()` avoids creating unnecessary intermediate lists, making it more memory efficient.

---

Why use `itertools.chain()`?

✓ Combines multiple iterables easily
✓ Memory efficient
✓ Works with lists, tuples, sets, generators, and more
✓ Commonly used in data processing and ETL pipelines

---

Challenge:

Given the following iterables:

python
fruits = ["Apple", "Banana"]
vegetables = ["Carrot", "Tomato"]
drinks = ["Water", "Juice"]
`

Use `itertools.chain()` to combine them into a single iterable and print all the items.
Python coding
⚡ Python Tip #34: The itertools.chain() Function The chain() function from Python's itertools module allows you to combine multiple iterables into a single iterator. It is a memory-efficient alternative to concatenating lists. --- Importing chain from…
🚀 Python Tip #35: The itertools.compress() Function

The compress() function from Python's itertools module filters data using a sequence of selectors.

It returns only the items whose corresponding selector is True.

---

Importing compress

from itertools import compress

---

Basic Example

from itertools import compress

letters = ["A", "B", "C", "D"]
selectors = [True, False, True, False]

result = list(compress(letters, selectors))

print(result)

Output:

['A', 'C']

Only the elements with a corresponding True value are returned.

---

Filtering Numbers

from itertools import compress

numbers = [10, 20, 30, 40, 50]
selectors = [0, 1, 0, 1, 1]

result = list(compress(numbers, selectors))

print(result)

Output:

[20, 40, 50]

In Python, 1 is treated as True and 0 as False.

---

Practical Example

Suppose you have a list of students and a list indicating who passed.

from itertools import compress

students = ["Ali", "Sara", "John", "Mariam"]
passed = [True, False, True, True]

successful = list(compress(students, passed))

print(successful)

Output:

['Ali', 'John', 'Mariam']

---

Why use compress()?

✓ Simple way to filter data
✓ Cleaner than writing manual loops
✓ Memory efficient
✓ Useful in data analysis, machine learning, and data preprocessing

---

Challenge:

Given the following lists:

products = [
"Laptop",
"Phone",
"Tablet",
"Monitor"
]

available = [
True,
False,
True,
True
]

Use `itertools.compress()` to create a list containing only the available products.
Python coding
🚀 Python Tip #35: The itertools.compress() Function The compress() function from Python's itertools module filters data using a sequence of selectors. It returns only the items whose corresponding selector is True. --- Importing compress from itertools…
💡 Python Tip #36: The itertools.accumulate() Function

The accumulate() function from Python's itertools module returns cumulative results as it processes an iterable.

It is useful for calculating running totals, cumulative products, and other progressive operations.

---

Importing accumulate

from itertools import accumulate

---

Basic Example

from itertools import accumulate

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

result = list(accumulate(numbers))

print(result)

Output:

[1, 3, 6, 10, 15]

Each value is the sum of all previous values.

---

Using Multiplication

You can change the operation by providing a function.

from itertools import accumulate
import operator

numbers = [1, 2, 3, 4]

result = list(accumulate(numbers, operator.mul))

print(result)

Output:

[1, 2, 6, 24]

---

Practical Example

Calculate a running bank balance.

from itertools import accumulate

transactions = [1000, -200, 500, -150, 300]

balance = list(accumulate(transactions))

print(balance)

Output:

[1000, 800, 1300, 1150, 1450]

Each value represents the account balance after each transaction.

---

Why use accumulate()?

✓ Calculates running totals automatically
✓ Supports custom operations like multiplication and maximum
✓ Eliminates manual loops
✓ Commonly used in finance, statistics, and data analysis

---

Challenge:

Given the following daily sales:

sales = [120, 180, 150, 200, 170]

Use `itertools.accumulate() to calculate the cumulative sales after each day.

Expected Output:

``
python
[120, 300, 450, 650, 820]
`
Python coding
💡 Python Tip #36: The itertools.accumulate() Function The accumulate() function from Python's itertools module returns cumulative results as it processes an iterable. It is useful for calculating running totals, cumulative products, and other progressive…
🐍 Python Tip #37: The itertools.cycle() Function

The cycle() function from Python's itertools module repeats the elements of an iterable indefinitely.

It is useful when you need to continuously loop through a sequence without restarting it manually.

---

Importing cycle

from itertools import cycle

---

Basic Example

from itertools import cycle

colors = cycle(["Red", "Green", "Blue"])

for _ in range(8):
print(next(colors))

Output:

Red
Green
Blue
Red
Green
Blue
Red
Green

The sequence repeats automatically.

---

Using next()

The next() function retrieves the next item from the iterator.

from itertools import cycle

numbers = cycle([1, 2, 3])

print(next(numbers))
print(next(numbers))
print(next(numbers))
print(next(numbers))

Output:

1
2
3
1

After reaching the last item, cycle() starts again from the beginning.

---

Practical Example

Rotate through a list of servers.

from itertools import cycle

servers = cycle([
"Server A",
"Server B",
"Server C"
])

for _ in range(6):
print(next(servers))

Output:

Server A
Server B
Server C
Server A
Server B
Server C

This technique is commonly used for round-robin scheduling.

---

Why use cycle()?

✓ Repeats items automatically
✓ Eliminates manual index management
✓ Memory efficient
✓ Useful for animations, scheduling, simulations, and game development

---

Challenge:

Given the following list:

traffic_lights = [
"Red",
"Yellow",
"Green"
]

Use `itertools.cycle()` to print the traffic light sequence 10 times.
Python coding
🐍 Python Tip #37: The itertools.cycle() Function The cycle() function from Python's itertools module repeats the elements of an iterable indefinitely. It is useful when you need to continuously loop through a sequence without restarting it manually. --…
🚀 Python Tip #38: The itertools.repeat() Function

The repeat() function from Python's itertools module returns the same value multiple times.

It is useful when you need a constant value in loops, function calls, or data generation.

---

Importing repeat

from itertools import repeat

---

Basic Example

from itertools import repeat

for value in repeat("Python", 5):
print(value)

Output:

Python
Python
Python
Python
Python

The string "Python" is repeated exactly 5 times.

---

Creating a List

from itertools import repeat

numbers = list(repeat(10, 4))

print(numbers)

Output:

[10, 10, 10, 10]

---

Using repeat() with map()

Suppose you want to multiply every number by 2.

from itertools import repeat

numbers = [1, 2, 3, 4]

result = list(map(pow, numbers, repeat(2)))

print(result)

Output:

[1, 4, 9, 16]

Here, `repeat(2) provides the exponent 2 for every call to pow().

---

Infinite Repetition

If you omit the second argument,
repeat() repeats forever.

``
python
from itertools import repeat

counter = repeat("Hello")

for _ in range(3):
print(next(counter))

Output:

python
Hello
Hello
Hello

Since the iterator is infinite, we use `next()` or limit it with a loop.

---

Why use `repeat()`?

✓ Generates constant values efficiently
✓ Works well with `map()` and other iterators
✓ Avoids creating unnecessary lists
✓ Commonly used in functional programming and data processing

---

Challenge:

Use `itertools.repeat()` to create a list containing the word:

python
"AI"

repeated **8 times**.

Expected Output:

python
['AI', 'AI', 'AI', 'AI', 'AI', 'AI', 'AI', 'AI']
`
Python coding
🚀 Python Tip #38: The itertools.repeat() Function The repeat() function from Python's itertools module returns the same value multiple times. It is useful when you need a constant value in loops, function calls, or data generation. --- Importing repeat…
💡 Python Tip #39: The itertools.takewhile() Function

The takewhile() function from Python's itertools module returns items from an iterable **as long as a condition remains True**.

Once the condition becomes False, the iteration stops immediately.

---

Importing takewhile

from itertools import takewhile

---

Basic Example

from itertools import takewhile

numbers = [2, 4, 6, 8, 9, 10, 12]

result = list(takewhile(lambda x: x % 2 == 0, numbers))

print(result)

Output:

[2, 4, 6, 8]

The iteration stops when it reaches 9 because it is not an even number.

---

Using a Numeric Condition

from itertools import takewhile

numbers = [5, 10, 15, 20, 30, 40]

result = list(takewhile(lambda x: x < 25, numbers))

print(result)

Output:

[5, 10, 15, 20]

Although 40 also doesn't satisfy the condition, the iteration already stopped at 30.

---

Working with Strings

from itertools import takewhile

words = [
"Apple",
"Ant",
"Ball",
"Cat"
]

result = list(takewhile(lambda word: word.startswith("A"), words))

print(result)

Output:

['Apple', 'Ant']

The iteration stops when "Ball" is encountered.

---

Important Note

takewhile() only checks items until the first condition fails.

It dnotot** continue searching the remaining elements.

---

Why use takewhile()?

✓ Stops processing as soon as a condition fails
✓ More efficient than checking every item
✓ Works with any iterable or generator
✓ Commonly used in data streams and lazy evaluation

---

Challenge:

Given the following list:

temperatures = [18, 20, 22, 24, 31, 28, 26]

Use `itertools.takewhile() to collect all temperatures that are **below 30**.

Expected Output:

``
python
[18, 20, 22, 24]
`