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 #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]
`
Python coding
πŸ’‘ 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. --- …
πŸš€ Python Tip #40: The itertools.dropwhile() Function

The dropwhile() function from Python's itertools module skips items from an iterable **as long as a condition is True**.

Once the condition becomes False, it returns that item and every remaining item.

---

Importing dropwhile

from itertools import dropwhile

---

Basic Example

from itertools import dropwhile

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

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

print(result)

Output:

[9, 10, 12]

The even numbers at the beginning are skipped. Once 9 is encountered, all remaining values are returned.

---

Using a Numeric Condition

from itertools import dropwhile

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

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

print(result)

Output:

[30, 40]

The function skips numbers less than 25 and starts returning values from 30.

---

Working with Strings

from itertools import dropwhile

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

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

print(result)

Output:

['Ball', 'Cat']

The words starting with "A" are skipped. After "Ball" is reached, all remaining words are returned.

---

takewhile() vs dropwhile()

from itertools import takewhile, dropwhile

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

print(list(takewhile(lambda x: x < 4, numbers)))
print(list(dropwhile(lambda x: x < 4, numbers)))

Output:

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

- `takewhile() keeps items while the condition is True.
-
dropwhile() skips items while the condition is True.

---

Why use
dropwhile()?

βœ“ Skips unwanted items efficiently
βœ“ Stops checking once the condition becomes
False
βœ“ Works with iterators and generators
βœ“ Useful for processing logs, streams, and large datasets

---

Challenge:

Given the following list:

``
python
scores = [45, 50, 55, 60, 72, 80, 90]

Use `itertools.dropwhile()` to skip all scores below `70`.

Expected Output:

python
[72, 80, 90]
`
Python coding
πŸš€ Python Tip #40: The itertools.dropwhile() Function The dropwhile() function from Python's itertools module skips items from an iterable **as long as a condition is True**. Once the condition becomes False, it returns that item and every remaining item.…
🐍 Python Tip #41: The itertools.tee() Function

The tee() function from Python's itertools module creates multiple independent iterators from a single iterable.

This is useful when you need to iterate over the same data more than once without recreating it.

---

Importing tee

from itertools import tee

---

Basic Example

from itertools import tee

numbers = [1, 2, 3, 4]

iterator1, iterator2 = tee(numbers)

print(list(iterator1))
print(list(iterator2))

Output:

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

Both iterators contain the same data.

---

Working with Generators

tee() is especially useful with generators, which can normally be used only once.

from itertools import tee

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

it1, it2 = tee(squares)

print(list(it1))
print(list(it2))

Output:

[0, 1, 4, 9, 16]
[0, 1, 4, 9, 16]

Without tee(), the generator would be exhausted after the first iteration.

---

Creating More Than Two Iterators

You can create as many independent iterators as needed.

from itertools import tee

letters = ["A", "B", "C"]

a, b, c = tee(letters, 3)

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

Output:

A
A
A

Each iterator maintains its own position independently.

---

Why use tee()?

βœ“ Creates multiple independent iterators
βœ“ Works with generators and other iterables
βœ“ Prevents data from being consumed after one iteration
βœ“ Useful in data pipelines and iterator-based programming

---

Challenge:

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

Use itertools.tee() to create two independent iterators.

- Use the first iterator to print all the numbers.
- Use the second iterator to print only the first five numbers.
Python coding
🐍 Python Tip #41: The itertools.tee() Function The tee() function from Python's itertools module creates multiple independent iterators from a single iterable. This is useful when you need to iterate over the same data more than once without recreating it.…
πŸš€ Python Tip #42: The itertools.zip_longest() Function

The zip_longest() function from Python's itertools module combines multiple iterables, just like zip(). However, unlike zip(), it continues until the longest iterable is exhausted.

Missing values are filled with a specified value (or None by default).

---

Importing zip_longest

from itertools import zip_longest

---

Basic Example

from itertools import zip_longest

names = ["Ali", "Sara", "John"]
scores = [90, 85]

result = list(zip_longest(names, scores))

print(result)

Output:

[
('Ali', 90),
('Sara', 85),
('John', None)
]

Since `scores is shorter, None is used for the missing value.

---

Using a Custom Fill Value

You can replace
None with any value using the fillvalue parameter.

``
python
from itertools import zip_longest

names = ["Ali", "Sara", "John"]
scores = [90, 85]

result = list(zip_longest(names, scores, fillvalue="N/A"))

print(result)

Output:

python
[
('Ali', 90),
('Sara', 85),
('John', 'N/A')
]

---

`zip()` vs `zip_longest()`

python
from itertools import zip_longest

list1 = [1, 2, 3]
list2 = ["A", "B"]

print(list(zip(list1, list2)))
print(list(zip_longest(list1, list2)))

Output:

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

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

- `zip()` stops when the shortest iterable ends.
- `zip_longest()` continues until the longest iterable ends.

---

Practical Example

python
from itertools import zip_longest

products = ["Laptop", "Phone", "Tablet"]
prices = [1200, 800]

for product, price in zip_longest(products, prices, fillvalue="Unknown"):
print(product, price)

Output:

python
Laptop 1200
Phone 800
Tablet Unknown

---

Why use `zip_longest()`?

βœ“ Combines iterables of different lengths
βœ“ Prevents data loss when one iterable is shorter
βœ“ Supports custom fill values
βœ“ Useful for data cleaning, reporting, and CSV processing

---

Challenge:

Given the following lists:

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

grades = [
"A",
"B"
]

Use `itertools.zip_longest()` with:

python
fillvalue = "Not Graded"

Expected Output:

python
[
('Ali', 'A'),
('Sara', 'B'),
('John', 'Not Graded'),
('Mariam', 'Not Graded')
]
`
Python coding
πŸš€ Python Tip #42: The itertools.zip_longest() Function The zip_longest() function from Python's itertools module combines multiple iterables, just like zip(). However, unlike zip(), it continues until the longest iterable is exhausted. Missing values are…
πŸ’‘ Python Tip #43: The collections.Counter Class

The Counter class from Python's collections module is a convenient way to count the occurrences of elements in an iterable.

It automatically creates a dictionary where the keys are the unique elements and the values are their counts.

---

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.

from collections import Counter

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

count = Counter(numbers)

print(count.most_common(2))

Output:

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

This returns the two most common elements and their frequencies.

---

Counting Words

from collections import Counter

sentence = "python is fun and python is powerful"

words = sentence.split()

count = Counter(words)

print(count)

Output:

Counter({
'python': 2,
'is': 2,
'fun': 1,
'and': 1,
'powerful': 1
})

---

Why use Counter?

βœ“ Counts elements automatically
βœ“ Eliminates manual counting loops
βœ“ Finds the most common items easily
βœ“ Commonly used in text analysis, data science, and frequency analysis

---

Challenge:

Given the following list:

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

Use `collections.Counter to:

1. Count how many votes each programming language received.
2. Display the most popular programming language using:

``
python
most_common(1)
`
Python coding
πŸ’‘ Python Tip #43: The collections.Counter Class The Counter class from Python's collections module is a convenient way to count the occurrences of elements in an iterable. It automatically creates a dictionary where the keys are the unique elements and the…
πŸš€ Python Tip #44: The collections.UserDict Class

The UserDict class from Python's collections module is a wrapper around the built-in dictionary.

It makes it easier to create custom dictionary classes by allowing you to override dictionary behavior.

---

Importing UserDict

from collections import UserDict

---

Basic Example

from collections import UserDict

class MyDictionary(UserDict):
pass

data = MyDictionary()

data["name"] = "Yehya"
data["age"] = 16

print(data)

Output:

{'name': 'Yehya', 'age': 16}

---

Customizing Dictionary Behavior

Suppose you want all keys to be stored in lowercase.

from collections import UserDict

class LowerDict(UserDict):
def __setitem__(self, key, value):
super().__setitem__(key.lower(), value)

data = LowerDict()

data["Name"] = "Ali"
data["AGE"] = 18

print(data)

Output:

{'name': 'Ali', 'age': 18}

---

Validating Values

You can also validate data before storing it.

from collections import UserDict

class PositiveNumbers(UserDict):
def __setitem__(self, key, value):
if value < 0:
raise ValueError("Only positive numbers are allowed.")
super().__setitem__(key, value)

numbers = PositiveNumbers()

numbers["a"] = 10
numbers["b"] = 20

print(numbers)

Output:

{'a': 10, 'b': 20}

Trying to store a negative number:

numbers["c"] = -5

Output:

ValueError: Only positive numbers are allowed.

---

Why use UserDict?

βœ“ Easily create custom dictionary classes
βœ“ Override dictionary behavior safely
βœ“ Add validation and custom logic
βœ“ Useful for configuration systems, caching, and data validation

---

Challenge:

Create a class named:

UpperCaseDict

using `UserDict.

Whenever a key is added, automatically convert it to uppercase.

Example:

``
python
data["name"] = "Yehya"
data["city"] = "Addis Ababa"

Expected Output:

python
{'NAME': 'Yehya', 'CITY': 'Addis Ababa'}
`