0% found this document useful (0 votes)
5 views55 pages

Dunder or Magic Methods in Python

Uploaded by

Shweta Verma
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views55 pages

Dunder or Magic Methods in Python

Uploaded by

Shweta Verma
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 55

Dunder or magic methods in Python

Python Magic methods are the methods starting and ending with double
underscores ‘__’. They are defined by built-in classes in Python and
commonly used for operator overloading.
They are also called Dunder methods, Dunder here means “Double Under
(Underscores)”.
Python Magic Methods
Built in classes define many magic methods, dir() function can show you
magic methods inherited by a class.
Example:
This code displays the magic methods inherited by int class.
# code
print(dir(int))

Output
['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__',
'__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__',
'__floor__', '__floordiv__', '__format__', '__ge__', '_...

Python Magic Methods


Below are the lists of Python magic methods and their uses.
Initialization and Construction
• __new__: To get called in an object’s instantiation.
• __init__: To get called by the __new__ method.
• __del__: It is the destructor.
Numeric magic methods
• __trunc__(self): Implements behavior for math.trunc()
• __ceil__(self): Implements behavior for math.ceil()
• __floor__(self): Implements behavior for math.floor()
• __round__(self,n): Implements behavior for the built-in round()
• __invert__(self): Implements behavior for inversion using the ~
operator.
• __abs__(self): Implements behavior for the built-in abs()
• __neg__(self): Implements behavior for negation
• __pos__(self): Implements behavior for unary positive
Arithmetic operators
• __add__(self, other): Implements behavior for the + operator
(addition).
• __sub__(self, other): Implements behavior for the – operator
(subtraction).
• __mul__(self, other): Implements behavior for the * operator
(multiplication).
• __floordiv__(self, other): Implements behavior for the // operator
(floor division).
• __truediv__(self, other): Implements behavior for the / operator (true
division).
• __mod__(self, other): Implements behavior for the % operator
(modulus).
• __divmod__(self, other): Implements behavior for the divmod()
function.
• __pow__(self, other): Implements behavior for the ** operator
(exponentiation).
• __lshift__(self, other): Implements behavior for the << operator (left
bitwise shift).
• __rshift__(self, other): Implements behavior for the >> operator (right
bitwise shift).
• __and__(self, other): Implements behavior for the & operator (bitwise
and).
• __or__(self, other): Implements behavior for the | operator (bitwise
or).
• __xor__(self, other): Implements behavior for the ^ operator (bitwise
xor).
• __invert__(self): Implements behavior for bitwise NOT using the ~
operator.
• __neg__(self): Implements behavior for negation using the – operator.
• __pos__(self): Implements behavior for unary positive using the +
operator.
String Magic Methods
• __str__(self): Defines behavior for when str() is called on an instance of
your class.
• __repr__(self): To get called by built-int repr() method to return a
machine readable representation of a type.
• __unicode__(self): This method to return an unicode string of a type.
• __format__(self, formatstr): return a new style of string.
• __hash__(self): It has to return an integer, and its result is used for
quick key comparison in dictionaries.
• __nonzero__(self): Defines behavior for when bool() is called on an
instance of your class.
• __dir__(self): This method to return a list of attributes of a class.
• __sizeof__(self): It return the size of the object.
Comparison magic methods
• __eq__(self, other): Defines behavior for the equality operator, ==.
• __ne__(self, other): Defines behavior for the inequality operator, !=.
• __lt__(self, other): Defines behavior for the less-than operator, <.
• __gt__(self, other): Defines behavior for the greater-than operator, >.
• __le__(self, other): Defines behavior for the less-than-or-equal-to
operator, <=.
• __ge__(self, other): Defines behavior for the greater-than-or-equal-to
operator, >=.
Dunder or Magic Methods in Python
Let’s see some of the Python magic methods with examples:
1. __init__ method
The __init__ method for initialization is invoked without any call, when an
instance of a class is created, like constructors in certain other programming
languages such as C++, Java, C#, PHP, etc.
These methods are the reason we can add two strings with the ‘+’ operator
without any explicit typecasting.
# declare our own string class
class String:

# magic method to initiate object


def __init__(self, string):
self.string = string

# Driver Code
if __name__ == '__main__':

# object creation
string1 = String('Hello')

# print object location


print(string1)

Output
<__main__.String object at 0x7f538c059050>

Awesome — you’re diving into Python’s magic (dunder) methods that


handle numeric operations
Let’s break each one down with simple examples to show what they do and
how to implement them.

1. __trunc__(self) – math.trunc()
Rounds a number towards zero (drops decimal part).
import math

class MyNumber:
def __init__(self, value):
self.value = value

def __trunc__(self):
return int(self.value)

x = MyNumber(5.9)
print(math.trunc(x)) # Output: 5

2. __ceil__(self) – math.ceil()
Rounds up to the nearest integer.
import math

class MyNumber:
def __init__(self, value):
self.value = value

def __ceil__(self):
return int(self.value) + (self.value % 1 > 0)

x = MyNumber(5.1)
print(math.ceil(x)) # Output: 6

3. __floor__(self) – math.floor()
Rounds down to the nearest integer.
import math

class MyNumber:
def __init__(self, value):
self.value = value

def __floor__(self):
return int(self.value)

x = MyNumber(5.9)
print(math.floor(x)) # Output: 5

4. __round__(self, n)
Defines behavior for round(obj, n).
class MyNumber:
def __init__(self, value):
self.value = value

def __round__(self, n=0):


return round(self.value, n)

x = MyNumber(5.6789)
print(round(x, 2)) # Output: 5.68

5. __invert__(self) – ~obj
Bitwise inversion (used with ~ operator).
class MyNumber:
def __init__(self, value):
self.value = value
def __invert__(self):
return ~self.value

x = MyNumber(5)
print(~x) # Output: -6

6. __abs__(self) – abs(obj)
Returns absolute value.
class MyNumber:
def __init__(self, value):
self.value = value

def __abs__(self):
return abs(self.value)

x = MyNumber(-7)
print(abs(x)) # Output: 7

7. __neg__(self) – -obj
Defines behavior for negation.
class MyNumber:
def __init__(self, value):
self.value = value

def __neg__(self):
return -self.value

x = MyNumber(10)
print(-x) # Output: -10

8. __pos__(self) – +obj
Defines behavior for unary plus.
class MyNumber:
def __init__(self, value):
self.value = value

def __pos__(self):
return +self.value

x = MyNumber(7)
print(+x) # Output: 7

Summary Table:
Method Triggered by Purpose

__trunc__ math.trunc(obj) Truncates decimal part

__ceil__ math.ceil(obj) Rounds up

__floor__ math.floor(obj) Rounds down

__round__ round(obj, n) Rounds to n decimal places

__invert__ ~obj Bitwise NOT

__abs__ abs(obj) Absolute value

__neg__ -obj Negation

__pos__ +obj Unary plus

Let me know if you want a combined class implementing all of these


together!

Absolutely! Let’s deep dive into lists in Python — one of the most powerful
and flexible data structures.
We’ll explore definition, properties, and all major operations with easy-to-
understand examples.

What is a List in Python?


A list is an ordered, mutable (changeable) collection of items.
my_list = [10, 20, 30, "Python", True]

Allows:
• Mixed data types
• Duplicates
• Nesting (lists inside lists)

Basic List Syntax


# Empty list
empty = []

# List with elements


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

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

print(fruits[0]) # apple
print(fruits[-1]) # cherry (last item)

List Operations (with Examples)

1. Add Items
fruits = ["apple", "banana"]

fruits.append("cherry") # Add at end


fruits.insert(1, "mango") # Add at specific index
fruits.extend(["kiwi", "grape"]) # Add multiple items

print(fruits)
# ['apple', 'mango', 'banana', 'cherry', 'kiwi', 'grape']

2. Remove Items
fruits = ["apple", "banana", "cherry", "banana"]

fruits.remove("banana") # Removes first 'banana'


fruits.pop() # Removes last item
fruits.pop(0) # Removes item at index 0
del fruits[0] # Deletes item at index 0
fruits.clear() # Empties the list

print(fruits)

3. Update Items
fruits = ["apple", "banana", "cherry"]
fruits[1] = "mango"
print(fruits) # ['apple', 'mango', 'cherry']
4. Searching
fruits = ["apple", "banana", "cherry"]

print("banana" in fruits) # True


print(fruits.index("banana")) # 1
print(fruits.count("banana")) # 1

5. Sorting and Reversing


nums = [3, 1, 4, 2]

nums.sort() # Ascending
nums.sort(reverse=True) # Descending
nums.reverse() # Reverse current order

print(nums)

6. Looping through a List


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

for fruit in fruits:


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

7. Slicing a List
nums = [10, 20, 30, 40, 50]

print(nums[1:4]) # [20, 30, 40]


print(nums[:3]) # [10, 20, 30]
print(nums[::-1]) # [50, 40, 30, 20, 10] (reverse)

8. Nested Lists
matrix = [
[1, 2],
[3, 4],
[5, 6]
]

print(matrix[1]) # [3, 4]
print(matrix[1][0]) # 3

Built-in List Functions


Function Description

append(x) Adds x at the end

extend(iter) Adds all items from iterable

insert(i, x) Inserts x at index i

remove(x) Removes first occurrence of x

pop([i]) Removes and returns item at index

clear() Removes all items

index(x) Returns first index of x

count(x) Counts occurrences of x

sort() Sorts the list

reverse() Reverses the list

copy() Returns a shallow copy

List Summary

• Mutable (can change contents)

• Ordered (items have index)

• Supports indexing, slicing, nesting

• Many built-in methods to manipulate


Sure! Let’s dive into working with numeric and string data in Python,
covering both basic and slightly advanced topics with examples.

Working with Numeric Data in Python


1. Types of Numeric Data
Python has three main numeric types:
• int → integers (e.g., 5, -10)
• float → floating-point numbers (e.g., 3.14, -2.5)
• complex → complex numbers (e.g., 3 + 2j)
x=5 # int
y = 3.14 # float
z = 2 + 3j # complex
2. Basic Arithmetic Operations
a = 10
b=3

print(a + b) # Addition → 13
print(a - b) # Subtraction → 7
print(a * b) # Multiplication → 30
print(a / b) # Division → 3.333...
print(a // b) # Floor division → 3
print(a % b) # Modulus → 1
print(a ** b) # Exponentiation → 1000
3. Built-in Functions
print(abs(-7)) #7
print(round(3.1415, 2)) # 3.14
print(pow(2, 3)) #8
4. Math Module
import math

print(math.sqrt(16)) # 4.0
print(math.factorial(5)) # 120
print(math.pi) # 3.141592...

Working with String Data in Python


1. Creating Strings
s1 = 'Hello'
s2 = "World"
s3 = '''Multiline
String'''
2. String Concatenation & Repetition
print(s1 + " " + s2) # Hello World
print(s1 * 3) # HelloHelloHello
3. Accessing Characters and Slicing
text = "Python"
print(text[0]) #P
print(text[-1]) #n
print(text[1:4]) # yth
4. String Methods
s = " hello PYTHON "

print(s.strip()) # "hello PYTHON"


print(s.lower()) # " hello python "
print(s.upper()) # " HELLO PYTHON "
print(s.replace("PYTHON", "World")) # " hello World "
print(s.split()) # ['hello', 'PYTHON']
5. Checking Content
name = "Alice123"

print(name.isalpha()) # False (contains numbers)


print(name.isdigit()) # False
print(name.isalnum()) # True (letters + digits)
print(name.startswith("A")) # True
print(name.endswith("3")) # True
6. f-Strings and Formatting
name = "Bob"
age = 25

print(f"My name is {name} and I'm {age} years old.")


7. String Length
text = "Data Science"
print(len(text)) # 12

Tip: Type Conversion Between Strings and Numbers


num = "100"
converted = int(num) + 5 # 105

stringified = str(105) + " apples" # "105 apples"

Absolutely! Let's dive deep into functions in Python — covering everything


from basics to advanced features with examples.

What is a Function?
A function is a block of code that performs a specific task and runs only
when called. Functions help you reuse code and organize logic efficiently.

1. Defining and Calling a Function


def greet():
print("Hello from the function!")

greet() # Calling the function

2. Parameters and Arguments


def greet(name): # 'name' is a parameter
print(f"Hello, {name}!")

greet("Alice") # "Alice" is an argument


greet("Bob")

3. Return Statement
Functions can return values using return.
def add(a, b):
return a + b

result = add(3, 5)
print(result) # 8

4. Default Parameters
You can assign default values to parameters.
def greet(name="Guest"):
print(f"Hello, {name}!")

greet() # Hello, Guest


greet("Sam") # Hello, Sam

5. Multiple Return Values


def get_stats(numbers):
return min(numbers), max(numbers), sum(numbers)

low, high, total = get_stats([1, 2, 3])


print(low, high, total) # 1 3 6

6. Arbitrary Arguments
Use *args for any number of positional arguments:
def total(*args):
return sum(args)

print(total(1, 2, 3)) #6
print(total(10, 20, 30, 40)) # 100
Use **kwargs for any number of keyword arguments:
def describe_person(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")

describe_person(name="Alice", age=30)

7. Lambda Functions (Anonymous Functions)


Useful for short, one-line functions.
square = lambda x: x * x
print(square(5)) # 25

add = lambda a, b: a + b
print(add(3, 7)) # 10

8. Nested Functions
You can define functions inside other functions.
def outer():
def inner():
print("Inside inner function")
inner()

outer()
9. Recursion
A function calling itself.
def factorial(n):
if n == 0:
return 1
return n * factorial(n - 1)

print(factorial(5)) # 120

10. Docstrings (Documentation Strings)


You can document your functions like this:
def greet(name):
"""This function greets the person by name."""
print(f"Hello, {name}!")

print(greet.__doc__)

11. Type Hints (Optional)


def add(a: int, b: int) -> int:
return a + b

12. Higher-Order Functions


Functions that take other functions as arguments or return them.
def apply(func, value):
return func(value)

def double(x):
return x * 2

print(apply(double, 4)) # 8

Quick Summary:

Feature Keyword / Usage

Define a function def

Return value return

Default argument def f(x=5)

Variable args *args, **kwargs

Anonymous function lambda

Type hints def f(x: int) -> int:

Would you like to go deeper into any specific part (like recursion, lambda,
decorators, etc.) or get practice problems on functions?
Awesome! Let’s break down three core programming concepts in Python:
1. Boolean Expressions
2. Selection Structures (if-else)
3. Iteration Structures (loops)
We’ll explore each with definitions, syntax, examples, and tips.

1. Boolean Expressions in Python

What is a Boolean?
A Boolean expression evaluates to either True or False.

Boolean Values:
True
False

Comparison Operators:

Operator Meaning Example

== Equal to x == 5

!= Not equal to x != 3

> Greater than x > 10

< Less than x<4

>= Greater or equal x >= 8

<= Less or equal x <= 6

Logical Operators:
Operator Meaning

and True if both are True

or True if at least one is True

not Inverts the Boolean value

a=5
b = 10

print(a > 0 and b > 0) # True


print(a > 10 or b == 10) # True
print(not a > 10) # True

2. Selection Structure (Decision Making)

The if Statement
age = 18

if age >= 18:


print("You're an adult.")

The if-else Statement


if age >= 18:
print("You can vote.")
else:
print("You can't vote yet.")

The if-elif-else Statement


score = 75

if score >= 90:


print("Grade: A")
elif score >= 80:
print("Grade: B")
elif score >= 70:
print("Grade: C")
else:
print("Grade: F")

Short-hand if
x=5
y = 10
print("x is greater") if x > y else print("y is greater")

3. Iteration Structure (Loops)


Python supports two primary loops: for and while.

for Loop
Used for iterating over a sequence (like a list, string, or range).
for i in range(5): # 0 to 4
print(i)
Example with a List:
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)
Nested Loop:
for i in range(2):
for j in range(3):
print(f"i={i}, j={j}")

while Loop
Used when the number of iterations is not known in advance.
count = 0
while count < 5:
print(count)
count += 1

break, continue, and pass


• break → Exits the loop
• continue → Skips current iteration
• pass → Placeholder (does nothing)
for i in range(5):
if i == 3:
break
print(i) # 0, 1, 2
for i in range(5):
if i == 2:
continue
print(i) # 0, 1, 3, 4
for i in range(3):
pass # used to write later

Summary Table

Concept Description

Boolean Expression Evaluates to True or False

if, elif, else Decision-making based on conditions

for loop Loop over a sequence (list, range, string, etc.)

while loop Loop while a condition is True

break Exit loop early

continue Skip current loop iteration

pass Placeholder for future code


Great! Let's explore working with lists in Python in detail. Lists are ordered,
mutable (changeable), and allow duplicates, making them one of the most
commonly used data structures in Python.

1. Creating a List
# List of integers
numbers = [1, 2, 3, 4, 5]

# List of mixed data types


mixed = [1, "apple", True, 3.14]

# Empty list
empty = []

2. Accessing Elements
fruits = ["apple", "banana", "cherry"]

print(fruits[0]) # apple
print(fruits[-1]) # cherry (last item)
print(fruits[1:]) # ['banana', 'cherry']
3. Modifying Lists
Change Item:
fruits[1] = "blueberry"
print(fruits) # ['apple', 'blueberry', 'cherry']
Add Items:
fruits.append("orange") # Add to end
fruits.insert(1, "kiwi") # Add at index 1
print(fruits)
Extend List:
more_fruits = ["mango", "grape"]
fruits.extend(more_fruits)

4. Removing Items
fruits.remove("banana") # Removes first occurrence
fruits.pop() # Removes last item
fruits.pop(0) # Removes item at index 0
del fruits[1] # Deletes item at index 1
fruits.clear() # Empties the list

5. Looping Through a List


for fruit in fruits:
print(fruit)
# Using index
for i in range(len(fruits)):
print(fruits[i])

6. List Functions and Methods


Length, Sorting, Reversing:
numbers = [4, 2, 7, 1]

print(len(numbers)) #4
numbers.sort() # [1, 2, 4, 7]
numbers.reverse() # [7, 4, 2, 1]
Other Useful Methods:

Method Description

append() Add single item

extend() Add multiple items

insert() Insert item at specific position

remove() Remove specific item

pop() Remove item at given position or last

clear() Remove all items

index() Get index of item


Method Description

count() Count occurrences

sort() Sort list

reverse() Reverse list

copy() Returns a shallow copy

nums = [1, 2, 2, 3]
print(nums.count(2)) # 2
print(nums.index(3)) # 3

7. List Comprehensions (Short, elegant way to create lists)


squares = [x**2 for x in range(5)] # [0, 1, 4, 9, 16]
even = [x for x in range(10) if x % 2 == 0]

8. Copying Lists
a = [1, 2, 3]
b = a.copy()
# or
b = list(a)
# or
b = a[:]

Avoid doing: b = a (this creates a reference, not a copy)


9. Nested Lists
matrix = [[1, 2], [3, 4]]

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

10. Membership Testing & Iteration


if "apple" in fruits:
print("Found apple!")

for i, fruit in enumerate(fruits):


print(i, fruit)

Summary Table:

Task Example

Create list l = [1, 2, 3]

Access item l[0]

Slice list l[1:3]

Add item l.append(4)

Insert item l.insert(1, 10)


Task Example

Remove item l.remove(2)

Loop over list for x in l:

List comprehension [x**2 for x in range(5)]

Would you like to move on to tuples, sets, or dictionaries next, or see mini-
projects that use lists (like to-do apps, menu systems, etc.)?

Perfect! Let’s dive into working with a list of lists in Python — often referred
to as a 2D list or matrix. This is useful for representing grids, tables,
matrices, or any nested data.

1. What is a List of Lists?


A list of lists is simply a list where each element is itself a list.
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]

2. Accessing Elements
print(matrix[0]) # [1, 2, 3] → first row
print(matrix[1][2]) # 6 → second row, third column
print(matrix[-1][0]) # 7 → last row, first column

3. Looping Through a List of Lists


a) Loop by Rows
for row in matrix:
print(row)
b) Loop by Rows and Columns
for row in matrix:
for item in row:
print(item, end=' ')
print()
c) With Indexes
for i in range(len(matrix)):
for j in range(len(matrix[i])):
print(f"matrix[{i}][{j}] = {matrix[i][j]}")

4. Modifying Elements
matrix[0][0] = 10
print(matrix[0]) # [10, 2, 3]

5. Adding Rows and Columns


Add a new row:
matrix.append([10, 11, 12])
Add a new column:
for row in matrix:
row.append(0)

6. Removing Rows and Columns


Remove a row:
del matrix[2] # Deletes 3rd row
Remove a column:
for row in matrix:
del row[1] # Deletes 2nd column

7. List Comprehension with List of Lists


# Create 3x3 matrix with all zeroes
zero_matrix = [[0 for _ in range(3)] for _ in range(3)]

# Multiply each value by 2


doubled = [[item * 2 for item in row] for row in matrix]

8. Common Use Cases


a) Sum of all elements
total = 0
for row in matrix:
total += sum(row)
b) Transposing a Matrix
(Switch rows with columns)
transposed = [[row[i] for row in matrix] for i in range(len(matrix[0]))]

9. Useful Functions

Task Code Example

Length of outer list len(matrix)

Length of row len(matrix[0])

Flatten 2D list [item for row in matrix for item in row]

All zeros 4x3 [[0]*3 for _ in range(4)]

10. Real Example: Student Marks Table


students = [
["Alice", 85, 90, 88],
["Bob", 78, 80, 85],
["Charlie", 92, 88, 91]
]
for student in students:
name = student[0]
scores = student[1:]
avg = sum(scores) / len(scores)
print(f"{name}'s average score: {avg}")

Bonus: Pretty Printing


for row in matrix:
print(' '.join(str(x) for x in row))

Would you like to explore matrix operations (like multiplication, diagonal


elements), or see real projects using list of lists (like a Sudoku board or Tic-
Tac-Toe game)?

Working with dates and times is super useful in Python — whether you’re
building reminders, event logs, or just formatting output.
Let’s break it down using the built-in datetime module (plus a bit of time and
calendar if needed).

1. Importing datetime module


import datetime
2. Getting Current Date and Time
from datetime import datetime

now = datetime.now()
print(now) # Full date & time
print(now.date()) # Just the date
print(now.time()) # Just the time
Attributes:
print(now.year)
print(now.month)
print(now.day)
print(now.hour)
print(now.minute)
print(now.second)

3. Creating Specific Dates and Times


from datetime import datetime

birthday = datetime(2000, 12, 15, 10, 30, 0)


print(birthday)

4. Formatting Dates (strftime)


Use .strftime() to convert date/time to a string format.
now = datetime.now()

print(now.strftime("%Y-%m-%d")) # 2025-04-22
print(now.strftime("%d/%m/%Y")) # 22/04/2025
print(now.strftime("%A, %B %d")) # Tuesday, April 22
Common Format Codes:

Code Meaning Example

%Y Year (4 digits) 2025

%y Year (2 digits) 25

%m Month (01–12) 04

%d Day (01–31) 22

%H Hour (00–23) 13

%I Hour (01–12) 01

%p AM/PM PM

%M Minute (00–59) 45

%S Second (00–59) 30

%A Weekday name Tuesday

%B Month name April

5. Parsing Date Strings (strptime)


Use .strptime() to convert a string into a datetime object.
from datetime import datetime

date_str = "22/04/2025"
parsed = datetime.strptime(date_str, "%d/%m/%Y")
print(parsed) # 2025-04-22 00:00:00

6. Working with timedelta (Date Arithmetic)


from datetime import timedelta, datetime

today = datetime.now()
one_week = timedelta(weeks=1)
future_date = today + one_week
past_date = today - timedelta(days=30)

print(future_date)
print(past_date)

7. Difference Between Two Dates


date1 = datetime(2025, 5, 1)
date2 = datetime(2025, 4, 22)
difference = date1 - date2
print(difference.days) # 9 days
print(difference.total_seconds()) # Seconds

8. Calendar Module (Optional)


import calendar

print(calendar.month(2025, 4))
print(calendar.isleap(2025)) # False

9. time Module (Optional)


import time

print(time.time()) # Seconds since 1970


print(time.ctime()) # Current time as string

10. Sleep / Delay


import time

print("Wait for 3 seconds...")


time.sleep(3)
print("Done!")
Summary

Task Tool / Method

Current datetime datetime.now()

Current date .date()

Format datetime .strftime("%Y-%m-%d")

Parse from string datetime.strptime()

Add/Subtract days timedelta(days=...)

Difference between dates date1 - date2

Pause execution time.sleep(seconds)

Bonus: Date of the Week


today = datetime.now()
print(today.strftime("%A")) # e.g. "Tuesday"

Want practice problems, mini-projects (like a countdown timer or reminder


tool), or more advanced date-time tasks (like timezone handling)?

Let's break down dictionaries in Python in full detail — they're powerful,


flexible, and super useful for managing key-value pairs (like JSON or
database records).
1. What is a Dictionary?
A dictionary is an unordered, mutable, indexed collection that stores data in
key: value pairs.
person = {
"name": "Alice",
"age": 25,
"city": "New York"
}

Keys must be unique and immutable (strings, numbers, tuples)

2. Accessing Dictionary Values


print(person["name"]) # Alice
Using .get() method (safe way):
print(person.get("age")) # 25
print(person.get("gender", "N/A")) # N/A if key not found

3. Adding or Updating Values


# Add a new key-value pair
person["email"] = "[email protected]"

# Update value
person["age"] = 26

4. Removing Items
person.pop("city") # Removes key 'city'
del person["age"] # Another way to remove
person.clear() # Empties the dictionary

5. Looping Through a Dictionary


# Loop through keys
for key in person:
print(key, person[key])

# Loop through key-value pairs


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

6. Dictionary Methods

Method Description

dict.get(k) Get value of key k, return None if missing

dict.keys() Return all keys

dict.values() Return all values


Method Description

dict.items() Return (key, value) pairs

dict.pop(k) Remove key k and return its value

dict.clear() Remove all items

dict.update() Merge another dict into this one

dict.copy() Returns a shallow copy

print(person.keys()) # dict_keys(['name', 'email'])


print(person.values()) # dict_values(['Alice', '[email protected]'])
print(person.items()) # dict_items([('name', 'Alice'), ('email',
'[email protected]')])

7. Creating Dictionaries
a) From Scratch
car = {"brand": "Toyota", "year": 2022}
b) Using dict() constructor
car = dict(brand="Toyota", year=2022)
c) From a list of tuples
pairs = [("a", 1), ("b", 2)]
d = dict(pairs)

8. Nested Dictionaries
students = {
"101": {"name": "Alice", "score": 85},
"102": {"name": "Bob", "score": 90}
}

print(students["101"]["score"]) # 85

9. Dictionary Comprehensions
squares = {x: x*x for x in range(1, 6)}
# Output: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

10. Checking Key/Value Existence


if "name" in person:
print("Key exists!")

if "Alice" in person.values():
print("Value exists!")

11. Merging Dictionaries (Python 3.9+)


a = {"x": 1, "y": 2}
b = {"y": 3, "z": 4}
merged = a | b # {'x': 1, 'y': 3, 'z': 4}
Quick Summary Table

Feature Syntax Example

Create d = {"a": 1, "b": 2}

Access d["a"] or d.get("a")

Add/Update d["c"] = 3

Delete d.pop("a"), del d["b"], d.clear()

Keys/Values d.keys(), d.values(), d.items()

Loop for k, v in d.items():

Check key "a" in d

Comprehension {k: k*k for k in range(5)}

Nested Access d["key"]["subkey"]

Merge (3.9+) `d3 = d1

Would you like to practice this with mini-projects? (like a student grade
tracker, phonebook, or JSON-like data reader)?

Let’s dive deep into Tuples in Python — what they are, how to use them, and
why they’re awesome. Tuples are like lists, but immutable, meaning once
created, they can’t be changed.

1. What is a Tuple?
A tuple is an ordered, immutable, indexed collection that can hold multiple
items.
my_tuple = (1, 2, 3)

Tuples can contain different data types:


mixed = (1, "hello", True, 3.14)

2. Creating Tuples
# Normal tuple
t = (1, 2, 3)

# Tuple without parentheses (tuple packing)


t = 1, 2, 3

# Single-element tuple (must have a comma)

t = (5,) # tuple

t = (5) # just an int

# Empty tuple
t = ()

3. Accessing Tuple Elements


t = (10, 20, 30, 40)
print(t[0]) # 10
print(t[-1]) # 40
print(t[1:3]) # (20, 30)

4. Immutability of Tuples
Tuples cannot be changed after creation:

t[0] = 100 # Error: 'tuple' object does not support item assignment

5. Looping Through Tuples


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

for item in t:
print(item)

6. Tuple Operations

Operation Example Result

Concatenation (1, 2) + (3, 4) (1, 2, 3, 4)

Repetition ("a",) * 3 ("a", "a", "a")

Membership "a" in ("a", "b") True

Length len((1, 2, 3)) 3


Operation Example Result

Index t.index("apple") Position of "apple"

Count t.count("banana") Number of times it appears

7. Tuple Methods
Tuples only have two methods:
t = (1, 2, 2, 3)

print(t.count(2)) # 2
print(t.index(3)) # 3

8. When to Use Tuples

Use Case Why Tuples?

Fixed data No accidental modifications

Faster than lists Less memory & immutable

Dictionary keys Only immutable types allowed

Multiple return values from funcs Easy to unpack

9. Tuple Packing and Unpacking


# Packing
point = (4, 5)
# Unpacking
x, y = point
print(x, y) # 4 5
You can also unpack in loops:
pairs = [(1, 'a'), (2, 'b'), (3, 'c')]

for num, letter in pairs:


print(num, letter)

10. Nested Tuples


nested = ((1, 2), (3, 4))
print(nested[0][1]) # 2

11. Convert Between List and Tuple


# List → Tuple
my_list = [1, 2, 3]
my_tuple = tuple(my_list)

# Tuple → List
my_list = list(my_tuple)
Summary Table

Feature Tuple Example Note

Create t = (1, 2) Fixed-size, immutable

Access t[0], t[-1] Supports indexing/slicing

Unpack a, b = t Tuple unpacking

Loop for x in t: Easy to iterate

Convert list(t) or tuple(l) List ↔ Tuple

Use in dict d[(x, y)] = value Valid as keys if immutable

Example Use Case: Returning Multiple Values


def get_stats(nums):
return (min(nums), max(nums), sum(nums)/len(nums))

stats = get_stats([10, 20, 30])


print(stats) # (10, 30, 20.0)

Want to try small tuple-based problems (like coordinate manipulation, or


student record handling)?

You might also like