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
When accessing dictionary values, using square brackets (
Python provides the
---
Using Square Brackets
Output:
---
What Happens if the Key Doesn't Exist?
Output:
The program stops because the key doesn't exist.
---
Using
Output:
Instead of raising an error,
---
Providing a Default Value
You can specify a default value if the key is missing.
Output:
---
Practical Example
Output:
---
Why use
✓ Prevents
✓ Makes your code more reliable
✓ Allows default values
✓ Commonly used when working with JSON data and APIs
---
Challenge:
Given the dictionary:
Use the
- The value of
- The value of
dict.get() MethodWhen 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
When working with dictionaries, you often need to check whether a key already exists before using it.
Python's
---
Importing
---
Without
Output:
---
With
Output:
---
Grouping Data
Example:
Output:
---
Common Default Types
---
Why use
✓ 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:
Use `defaultdict(list)
{
'Mammal': ['Lion', 'Tiger'],
'Bird': ['Eagle', 'Parrot'],
'Fish': ['Salmon']
}
collections.defaultdict ClassWhen 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
defaultdictfrom collections import defaultdict
---
Without
defaultdictscores = {}
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
defaultdictfrom 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
Some functions perform the same calculations repeatedly, which can slow down your program.
Python provides the
---
Importing
---
Without
This works, but it recalculates the same values many times, making it slow.
---
With
The result is the same, but the function runs much faster because previous results are stored in memory.
---
How It Works
- `@lru_cache
from functools import lru_cache
@lru_cache(maxsize=None)
def square(n):
print("Calculating...")
return n ** 2
print(square(5))
print(square(5))
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.
functools.lru_cache DecoratorSome 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_cachefrom functools import lru_cache
---
Without
lru_cachedef 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_cachefrom 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
``pythonfrom 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
When creating classes that mainly store data, Python provides the
It automatically generates methods like
---
Importing
---
Without
---
With
Output:
---
Comparing Objects
Output:
Without
---
Using Default Values
Output:
---
Why use
✓ Less boilerplate code
✓ Automainitcreates
✓ Improves readability
✓ Ideal for configuration objects, API responses, and data models
---
Challenge:
Create a
Then create an object and print it.
dataclass DecoratorWhen 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
dataclassfrom dataclasses import dataclass
---
Without
@dataclassclass 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
@dataclassfrom 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
The
It is useful for generating all possible combinations.
---
Importing
---
Basic Example
Output:
---
Converting to a List
If you want to store all combinations:
Output:
---
Repeating an Iterable
Use the
Output:
---
Why use
✓ 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:
Use `itertools.product()` to generate every possible outfit combination.
itertools.product() FunctionThe
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
productfrom 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
The
It is useful for organizing and summarizing data.
---
Importing
---
Basic Example
Output:
---
Grouping Strings
Output:
Notice that the last
---
Grouping Objects
Output:
---
Important Note
If your data is not already sorted by the grouping key, sort it first.
This ensures that all items with the same key appear together.
---
Why use
✓ 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:
Sort the list and use
Expected Output:
itertools.groupby() FunctionThe
groupby() function from Python's itertools module groups consecutive items that have the same key.It is useful for organizing and summarizing data.
---
Importing
groupbyfrom 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
When optimizing your code, don't guess which approach is faster—measure it.
Python's
---
Importing
---
Basic Example
Output:
(The exact time will vary depending on your computer.)
---
Comparing Two Approaches
Method 1
Method 2
By comparing the results, you can determine which approach is faster.
---
Using a Function
---
Why use
✓ 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
Method 1:
Method 2:
Use the
timeit ModuleWhen 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
timeitimport 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
Sometimes you expect an exception to occur and want to ignore it safely.
Python's
---
Importing
---
Without
This works, but it becomes repetitive if used frequently.
---
With
If `data.txt
from contextlib import suppress
with suppress(FileNotFoundError, ZeroDivisionError):
print(10 / 0)
python
temp.txt
Use `contextlib.suppress()` so that if the file does not exist, the program continues without raising an error.
contextlib.suppress() Context ManagerSometimes 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
suppressfrom 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.
``pythonfrom 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
Searching for files manually can be tedious, especially in large directories.
Python's
---
Importing
---
Finding All Python Files
Output:
The `*.py
from pathlib import Path
folder = Path("documents")
for file in folder.glob("*.txt"):
print(file.name)
python
from pathlib import Path
folder = Path(".")
for file in folder.rglob("*.py"):
print(file)
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.
pathlib.Path.glob() MethodSearching 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
Pathfrom 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
``pythonfrom 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
Python lists are excellent for most tasks, but they become inefficient when adding or removing items from the beginning.
The
---
Importing
---
Creating a Deque
Output:
---
Adding Elements
Append to the right:
Output:
Append to the left:
Output:
---
Removing Elements
Remove from the right:
Remove from the left:
Example:
Output:
---
Limiting the Size
A deque can have a maximum length.
Output:
The oldest item is automatically removed when the limit is exceeded.
---
Why use
✓ Fast insertions and deletions from both ends
✓ More efficient than lists for queue operations
✓ Supports fixed-size queues with
✓ Commonly used in task scheduling, caching, and breadth-first search (BFS)
---
Challenge:
Create a deque with a maximum length of
Then:
1. Add the numbers
2. Print the deque.
3. Explain why the first two numbers are no longer present.
collections.deque ClassPython 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
dequefrom 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
A
It makes your code more readable and easier to understand.
---
Importing
---
Creating a
Output:
---
Accessing Values
You can access values using their field names.
Output:
---
Using Indexes
A
Output:
---
Converting to a Dictionary
Use the
Output:
---
Why use
✓ 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
Create an object with your own values and print:
- The title
- The author
- The number of pages
- The dictionary representation using
collections.namedtuple ClassA
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
namedtuplefrom collections import namedtuple
---
Creating a
namedtuplefrom 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
Sometimes you need to work with multiple dictionaries as if they were a single dictionary.
Python's
---
Importing
---
Basic Example
Output:
---
Accessing Values
You can access values just like a normal dictionary.
Output:
---
Handling Duplicate Keys
If multiple dictionaries contain the same key,
Output:
---
Updating Values
Changes affect only the first dictionary.
Output:
---
Why use
✓ 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:
Use `ChainMap
collections.ChainMap ClassSometimes 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
ChainMapfrom 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
Sometimes you repeatedly call a function with the same arguments.
Python's
---
Importing
---
Basic Example
Output:
The `square()
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))
python
20
30
python
from functools import partial
def greet(greeting, name):
return f"{greeting}, {name}!"
say_hello = partial(greet, "Hello")
print(say_hello("Yehya"))
python
Hello, Yehya!
python
def calculate(price, tax):
return price + tax
python
add_vat
python
tax = 15
python
price = 200
functools.partial() FunctionSometimes 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
partialfrom 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
``pythonfrom 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
Although modern Python dictionaries preserve insertion order, the
It is available in the
---
Importing
---
Creating an
Output:
---
Moving an Item
You can move an existing key to the beginning or end of the dictionary.
Output:
---
Removing the First or Last Item
The
Output:
Using `last=False
{
"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`.
collections.OrderedDict ClassAlthough 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
OrderedDictfrom collections import OrderedDict
---
Creating an
OrderedDictfrom 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
When working with large iterables, you may only need a portion of the data.
Python's
---
Importing
---
Basic Example
Output:
---
Specifying a Start and Stop
Output:
---
Using a Step
Just like normal slicing, you can specify a step value.
Output:
---
Why Use
Unlike normal list slicing,
Example:
Output:
Only the required values are generated.
---
Why use
✓ 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
Then use
without converting the entire generator into a list.
itertools.islice() FunctionWhen 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
islicefrom 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
The
It is a memory-efficient alternative to concatenating lists.
---
Importing
---
Basic Example
Output:
---
Combining Multiple Iterables
Output:
---
Using
If your iterables are stored inside another iterable, use
Output:
---
Why Use
Without
With `chain()
from itertools import chain
result = chain(list1, list2)
print(list(result))
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.
itertools.chain() FunctionThe
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
chainfrom 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()
:
``pythonfrom 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
The
It returns only the items whose corresponding selector is
---
Importing
---
Basic Example
Output:
Only the elements with a corresponding
---
Filtering Numbers
Output:
In Python,
---
Practical Example
Suppose you have a list of students and a list indicating who passed.
Output:
---
Why use
✓ 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:
Use `itertools.compress()` to create a list containing only the available products.
itertools.compress() FunctionThe
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
compressfrom 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
The
It is useful for calculating running totals, cumulative products, and other progressive operations.
---
Importing
---
Basic Example
Output:
Each value is the sum of all previous values.
---
Using Multiplication
You can change the operation by providing a function.
Output:
---
Practical Example
Calculate a running bank balance.
Output:
Each value represents the account balance after each transaction.
---
Why use
✓ 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:
Use `itertools.accumulate()
[120, 300, 450, 650, 820]
itertools.accumulate() FunctionThe
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
accumulatefrom 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
The
It is useful when you need to continuously loop through a sequence without restarting it manually.
---
Importing
---
Basic Example
Output:
The sequence repeats automatically.
---
Using
The
Output:
After reaching the last item,
---
Practical Example
Rotate through a list of servers.
Output:
This technique is commonly used for round-robin scheduling.
---
Why use
✓ Repeats items automatically
✓ Eliminates manual index management
✓ Memory efficient
✓ Useful for animations, scheduling, simulations, and game development
---
Challenge:
Given the following list:
Use `itertools.cycle()` to print the traffic light sequence 10 times.
itertools.cycle() FunctionThe
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
cyclefrom 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
The
It is useful when you need a constant value in loops, function calls, or data generation.
---
Importing
---
Basic Example
Output:
The string
---
Creating a List
Output:
---
Using
Suppose you want to multiply every number by 2.
Output:
Here, `repeat(2)
from itertools import repeat
counter = repeat("Hello")
for _ in range(3):
print(next(counter))
python
Hello
Hello
Hello
python
"AI"
python
['AI', 'AI', 'AI', 'AI', 'AI', 'AI', 'AI', 'AI']
itertools.repeat() FunctionThe
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
repeatfrom 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.
``pythonfrom 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']
`