Python Programming -Basics to Advanced (1)
Python Programming -Basics to Advanced (1)
Programming
CPython
Jython
PyPy (interpreter)
Boolean Type
• Swap
#include <stdio.h> Good swap
13
#include <stdio.h> Good swap
14
#include <stdio.h> Good swap
15
#include <stdio.h> Good swap
16
#include <stdio.h> Good swap
17
#include <stdio.h> Good swap
18
#include <stdio.h> Good swap
19
Python Swap
# Function to swap two numbers in Python
def swap(a, b):
return b, a
x=1
y=2
# Swapping the values of x and y
x, y = swap(x, y)
print(x, y) # Output: 2 1
For Loop in Python
for item in sequence:
# code block to be executed
for i in range(5):
print(i)
List in Python
•# Creating a list •#Adding item at specific position
•my_list = [1, 2, 3, 4, 5] •my_list.insert(1, "inserted")
•# Accessing elements •print(my_list) # Output: [1,
•print(my_list[0]) # Output: 1 'inserted', 2, 3, 4]
•#Popping an element from a
•# Adding an element
specific index (removes and
•my_list.append(6) returns):
•# Removing an element •my_list.pop(2)
•my_list.remove(3) •print(my_list) # Output: [1,
•# Checking the list 'inserted', 4]
•print(my_list) # Output: [1, 2, 4, 5,
6]
List
my_list = [1, 2, 3, 4, 5]
print(len(my_list)) # Output: 5
2. List with Multiple Data Types
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# Accessing elements
print(matrix[0][1]) # Output: 2 (first row, second element)
3D List
cube = [
[[1, 2], [3, 4]],
[[5, 6], [7, 8]]
]
# Accessing elements
print(cube[1][0][1]) # Output: 6
5. List Slicing
my_list = [1, 2, 3, 4, 5]
sliced_list = my_list[1:4] # Slices from index 1 to 3 (excludes index 4)
print(sliced_list) # Output: [2, 3, 4]
6. Iterating through a List
my_list = [10, 20, 30]
for item in my_list:
print(item) or print (*[item])
my_list.sort(reverse=True) # Descending
print(my_list) # Output: [4, 3, 2, 1]
11. Reversing a List
my_list = [1, 2, 3]
my_list.reverse()
print(my_list) # Output: [3, 2, 1]
Python
Dictionary
• A dictionary in Python is a collection of key-value pairs, where each key maps to a
value.
#Creating a dictionary
student = {
"name": "Jamal",
"age": 12,
"grade": "6th",
"subjects": ["Math", "Science", "English"]
}
# Accessing elements
print(student["name"]) # Output: Jamal
print(student["subjects"]) # Output: ['Math', 'Science', 'English’]
print(student) # Output: {'name': ‘Jamal', 'age': 12, 'grade': '6th', 'subjects': ['Math', 'Science', 'English']}
List of Dictionaries
•# Creating a list of dictionaries •# Looping through all student
•students = [ records
• {"name": “Jamal", "age": 12, "grade": •for student in students:
"6th"},
• print(f"{student['name']} is in
• {"name": "Ali", "age": 13, "grade":
grade {student['grade']}.")
"7th"},
• {"name": "Bilal", "age": 11, "grade":
"5th"}
•]
student = {
"name": "John",
"age": 12,
"grade": "6th"
}
Dictionary Methods
Method Description Example
keys() Returns a list of dictionary student.keys() → ['name',
keys 'age', 'grade']
values() Returns a list of dictionary student.values() → ['John',
values 12, '6th']
items() Returns a list of key-value student.items() →
pairs as tuples [('name', 'John'), ('age',
12)]
get(key) Returns the value for a student.get("name") →
given key, or None if key 'John'
doesn’t exist
update() Merges another dictionary student.update({"age":
into the current one 13}) → Updates 'age' to
13
Checking for a Key
if "name" in student:
print("Name is present in the dictionary.")
Looping Through a Dictionary
for key in student:
print(key)
# Sorting by values
sorted_by_values = {key: value for key, value in
sorted(student.items(), key=lambda item: item[1])}
•def function_name(parameters):
• # Function body
Defining a
Function •def greet(name):
• print(f"Hello, {name}!")
Calling a Function
greet(“Ali") # Output: Hello, Ali!
Parameters and Arguments
• Parameters: Variables listed in the function definition.
• Arguments: Values you pass to the function when
calling it.
square = lambda x: x ** 2
print(square(5)) # Output: 25
Scope of Variables
• Local Scope: Variables defined within a function are only
accessible inside that function.
• Global Scope: Variables defined outside any function are
accessible throughout the program.
Scope Variables
x = 10 # Global variable
def change_x():
x = 5 # Local variable
print("Inside function:", x)
x = 10
def change_global_x():
global x
x=5
change_global_x()
print(x) # Output: 5
nonlocal Keyword
• The nonlocal keyword is used to modify a variable in the
enclosing (non-global) scope.
def outer_function():
x = 10
def inner_function():
nonlocal x
x = 20
inner_function()
print(x) # Output: 20
Function Documentation
• You can add a docstring to a function to describe its
purpose.
• Use triple quotes """ to define a docstring.
def add(a, b):
"""This function adds two numbers."""
return a + b
class Car:
wheels = 4 # Class attribute (shared by all instances)
my_car = Car("Toyota")
print(my_car.model) # Public: Accessible
print(my_car._fuel) # Protected: Accessible, but not recommended
# print(my_car.__engine) # Private: Raises an AttributeError
Inheritance
• Inheritance allows one class to inherit attributes and methods from
another class.
• The parent class is called the superclass, and the class that inherits is
called the subclass.
class Vehicle:
def __init__(self, brand):
self.brand = brand
class Animal(ABC):
@abstractmethod
def sound(self):
pass
class Dog(Animal):
def sound(self):
return "Bark"
Without Abstraction
class CreditCard:
def pay_with_card(self, amount):
print(f"Paid ${amount} using Credit Card")
class PayPal:
def paypal_payment(self, amount):
print(f"Paid ${amount} using PayPal")
Without Abstration
def process_payment(payment_method, amount):
if isinstance(payment_method, CreditCard):
payment_method.pay_with_card(amount)
elif isinstance(payment_method, PayPal):
payment_method.paypal_payment(amount)
else:
raise ValueError("Unsupported payment method")
Without Abstraction
cc = CreditCard()
pp = PayPal()
process_payment(cc, 100)
process_payment(pp, 200)
With Abstraction
from abc import ABC, abstractmethod
class PayPal(Payment):
def pay(self, amount):
print(f"Paid ${amount} using PayPal")
process_payment(cc, 100)
process_payment(pp, 200)
Dunder (Magic) Methods
• These are special methods with double underscores
(like __init__, __str__, etc.).
• They allow customization of certain operations (like
string representation, object comparisons, etc.)
Dunder methods
Class Car:
def __init__(self, model):
self.model = model
def __str__(self):
return f"Car model: {self.model}"
my_car = Car("Toyota")
print(my_car) # Output: Car model: Toyota
Dunder Methods
Common dunder methods:
__init__(self): Constructor
__str__(self): String representation
__len__(self): Defines the behavior for the len()
function
__eq__(self, other): Used for comparison (e.g., ==)
Consider a graph
Nodes: A, B, C, D, E, F, G, H
A Edges:
/ \
B C A↔B
/\ \ A↔C
D E F B↔D
\ / B↔E
C↔F
G H
F↔H
D↔G
The DFS Data Structure
def __str__(self):
"""String representation of the node."""
return (f"Node(state={self.state}, "
f"parent={self.parent.state if self.parent else None}, "
f"path_cost={self.path_cost})")
Graph Generation
# Sample graph creation
def create_graph():
# Create nodes
A = Node('A')
B = Node('B', parent=A, path_cost=1)
C = Node('C', parent=A, path_cost=1)
D = Node('D', parent=B, path_cost=2)
E = Node('E', parent=B, path_cost=2)
F = Node('F', parent=C, path_cost=2)
G = Node('G', parent=D, path_cost=3)
H = Node('H', parent=F, path_cost=3)
Explanation
Creating the Graph: