Here
Here
count = 1
while count <= 5:
print(count)
count += 1
Loop Control Statements:
• break: Exits the loop immediately.
• continue: Skips the remaining code inside the loop for the current iteration.
• pass: Placeholder that does nothing and is used syntactically.
Example:
python
Copy code
for letter in "Python":
if letter == "h":
break # Loop will terminate when letter is 'h'
print(letter)
1.6 Functions
Defining a Function:
A function is defined using the def keyword, followed by the function name and
parentheses.
Example:
python
Copy code
def greet(name):
print(f"Hello, {name}!")
2.1.2 Encapsulation
Encapsulation hides the internal state of an object and restricts access to it using
methods (getters and setters). Private attributes are prefixed with double underscores
(__).
Example:
python
Copy code
class BankAccount:
def __init__(self, balance):
self.__balance = balance # Private attribute
account = BankAccount(1000)
print(account.get_balance()) # Output: 1000
2.1.3 Inheritance
Inheritance allows a new class (child class) to inherit attributes and methods from an
existing class (parent class).
Types of Inheritance:
1. Single Inheritance
2. Multiple Inheritance
3. Multilevel Inheritance
4. Hierarchical Inheritance
5. Hybrid Inheritance
Example:
python
Copy code
# Parent class
class Animal:
def speak(self):
print("Animal sound")
dog = Dog()
dog.speak() # Output: Animal sound
dog.bark() # Output: Dog barks
2.1.4 Polymorphism
Polymorphism allows methods to have the same name but behave diverently
depending on the object calling them.
Example:
python
Copy code
class Animal:
def sound(self):
pass
class Dog(Animal):
def sound(self):
print("Bark")
class Cat(Animal):
def sound(self):
print("Meow")
dog = Dog()
cat = Cat()
animal_sound(dog) # Output: Bark
animal_sound(cat) # Output: Meow
Example:
python
Copy code
try:
x = int(input("Enter a number: "))
y = 10 / x
except ValueError:
print("Invalid input. Please enter a number.")
except ZeroDivisionError:
print("Division by zero is not allowed.")
else:
print(f"Result: {y}")
finally:
print("Execution completed.")
def check_positive(number):
if number < 0:
raise NegativeValueError("Negative value not allowed!")
try:
check_positive(-5)
except NegativeValueError as e:
print(e) # Output: Negative value not allowed!
# File: main.py
import mymodule
mymodule.greet("Alice") # Output: Hello, Alice!
4.1.1 Decorators
What are Decorators?
A decorator is a higher-order function that takes another function as an argument and
extends or modifies its behavior without changing its actual code.
Decorators are commonly used for logging, access control, measuring execution time,
and other cross-cutting concerns.
Syntax and Usage:
Decorators are defined using the @decorator_name syntax above the function
definition.
Example:
python
Copy code
def decorator_function(original_function):
def wrapper_function(*args, **kwargs):
print(f"Wrapper executed before {original_function.__name__}")
return original_function(*args, **kwargs)
return wrapper_function
@decorator_function
def display():
print("Display function executed")
display()
Output:
css
Copy code
Wrapper executed before display
Display function executed
4.1.2 Generators
What are Generators?
Generators are a special type of iterator in Python that allow you to iterate over a
sequence of values without creating a large in-memory list. They are defined using a
function with the yield keyword instead of return.
Advantages:
• Memory-evicient as they generate values on the fly without storing them all at
once.
• Suitable for working with large datasets or infinite sequences.
Example:
python
Copy code
def countdown(num):
while num > 0:
yield num
num -= 1
@classmethod
def get_num_of_employees(cls):
return cls.num_of_employees
emp1 = Employee("Alice")
emp2 = Employee("Bob")
print(Employee.get_num_of_employees()) # Output: 2
def print_numbers():
for i in range(1, 6):
print(f"Number: {i}")
def print_letters():
for letter in "ABCDE":
print(f"Letter: {letter}")
# Creating threads
thread1 = threading.Thread(target=print_numbers)
thread2 = threading.Thread(target=print_letters)
# Starting threads
thread1.start()
thread2.start()
print("Threads completed.")
Output:
makefile
Copy code
Number: 1
Letter: A
Number: 2
Letter: B
Number: 3
Letter: C
Number: 4
Letter: D
Number: 5
Letter: E
Threads completed.
4.2.2 Multiprocessing
What is Multiprocessing?
Multiprocessing creates separate processes, each with its own memory space, allowing
true parallel execution. The multiprocessing module enables parallel processing for
CPU-bound tasks.
Usage:
Suitable for CPU-bound operations like mathematical calculations or data processing.
Example:
python
Copy code
import multiprocessing
def square_number(number):
return number * number
if __name__ == '__main__':
numbers = [1, 2, 3, 4, 5]
with multiprocessing.Pool() as pool:
results = pool.map(square_number, numbers)
print(results) # Output: [1, 4, 9, 16, 25]
4.2.3 Asynchronous Programming
What is Asynchronous Programming?
Asynchronous programming allows a program to perform non-blocking operations,
making it suitable for I/O-bound operations like web scraping, file I/O, and network
requests. The asyncio module enables asynchronous programming using
the async and await keywords.
Usage:
Used for building responsive applications that handle multiple I/O-bound tasks
simultaneously.
Example:
python
Copy code
import asyncio
asyncio.run(main())
Output:
kotlin
Copy code
Fetching data...
Fetching data...
Data fetched!
Data fetched!
@logger
def add(a, b):
return a + b
asyncio.run(main())
@time_it
def compute_square(numbers):
return [x * x for x in numbers]
numbers = [1, 2, 3, 4, 5]
square_thread.join()