BCA II Semester (Rev NEP)
Python Programming (C2BCA1T2)
STUDY MATERIAL
UNIT-II
A MODULAR APPROACH TO PROGRAM ORGANIZATION
Importing Modules:
In Python, modules are files that contain Python code (functions, classes, and variables)
that can be reused across different programs. Importing modules allows you to use pre-written
code, organize your project, and enhance functionality.
1. Importing a Module
You can import a module using the import keyword.
Example:
import math # Imports the built-in math module
print(math.sqrt(25)) # Output: 5.0
2. Importing Specific Functions or Variables
Instead of importing the entire module, you can import only the functions or variables you need.
Example:
from math import sqrt, pi
print(sqrt(36)) # Output: 6.0
print(pi) # Output: 3.141592653589793
3. Using an Alias (as)
You can rename a module or function using an alias for convenience.
Example:
import numpy as np # Renaming numpy module as np
print(np.array([1, 2, 3])) # Creates a NumPy array
from math import factorial as fact
print(fact(5)) # Output: 120
4. Importing Everything (*)
You can import all functions and variables from a module, but this is not recommended as it may
cause naming conflicts.
Example:
from math import * # Importing all functions and variables
print(sin(90)) # Output: 0.8939966636005579 (90 degrees in radians)
5. Importing Custom Modules
You can create your own module and import it into another Python file.
Example (custom module - mymodule.py):
# mymodule.py
def greet(name):
return f"Hello, {name}!"
Using the module in another file:
import mymodule
print(mymodule.greet("Alice")) # Output: Hello, Alice!
6. Checking Installed Modules
To see all installed modules, run:
Example:
help("modules")
7. Finding Module Location
To find where a module is installed:
Example:
import os
print(os. file )
8. Installing External Modules (Using pip)
Some modules are not built into Python and need to be installed using pip (Python's package
manager).
Example:
pip install requests # Installing the 'requests' module
Then you can use it in your script:
import requests
response = requests.get("https://www.google.com")
print(response.status_code) # Output: 200
9. Reloading a Module
If you modify a module after importing it, you need to reload it:
Example:
import importlib
import mymodule
importlib.reload(mymodule)
Defining Your Own Modules:
A module in Python is simply a file containing Python code (functions, classes, and variables)
that can be reused in multiple programs. Creating your own module allows you to organize your
code efficiently.
1. Creating a Module
To create a module, simply create a .py file with some functions or variables.
Example (mymodule.py):
# mymodule.py
def greet(name):
return f"Hello, {name}!"
def add(a, b):
return a + b
PI = 3.14159
2. Importing and Using a Custom Module
After creating mymodule.py, you can import it into another script.
Example (main.py):
import mymodule # Importing the custom module
print(mymodule.greet("Alice")) # Output: Hello, Alice!
print(mymodule.add(5, 3)) # Output: 8
print(mymodule.PI) # Output: 3.14159
3. Importing Specific Functions or Variables
Instead of importing the entire module, you can import only specific items.
Example:
from mymodule import greet, add
print(greet("Bob")) # Output: Hello, Bob!
print(add(10, 5)) # Output: 15
4. Using an Alias for a Module
You can give a shorter alias for easier usage.
Example:
import mymodule as mm
print(mm.greet("Charlie")) # Output: Hello, Charlie!
print(mm.add(2, 7)) # Output: 9
5. Checking Module Location
To see where Python is loading the module from:
Example:
import mymodule
print(mymodule. file ) # Shows the file path of the module
6. Storing Modules in a Package
If you want to organize multiple related modules, you can place them in a package (a directory
with an init .py file).
myproject/
│── main.py
│── mypackage/
│ │── init .py
│ │── mymodule.py
│ │── anothermodule.py
Inside mypackage/ init .py, you can initialize the package.
Now, you can import it like this:
from mypackage import mymodule
print(mymodule.greet("David"))
7. Reloading a Module
If you modify a module after importing it, Python does not automatically reload it. You can force
a reload using importlib.
Example:
import importlib
import mymodule
importlib.reload(mymodule) # Reloads the module after changes
8. Running a Module as a Script
You can make a module executable by adding:
Example:
if name == " main ":
print(greet("Eve"))
If you run mymodule.py directly, it will execute this block, but when imported, it won't run.
Testing Code Semi Automatically Grouping Functions Using Methods: Modules,
Classes, and Methods, Calling Methods the Object-Oriented Way:
In Python, you can structure your code using modules, classes, and methods to make it
more organized and reusable. You can also perform semi-automatic testing to verify that your
functions and methods work correctly.
Grouping Functions Using Modules
A module is a file that contains Python code. You can store multiple functions inside a module
and import them when needed.
Example (math_operations.py):
# math_operations.py
def add(a, b):
return a + b
def subtract(a, b):
return a - b
def multiply(a, b):
return a * b
Using the Module in Another File (main.py):
import math_operations
print(math_operations.add(5, 3)) # Output: 8
print(math_operations.subtract(10, 4)) # Output: 6
print(math_operations.multiply(6, 7)) # Output: 42
Grouping Functions Using Classes & Methods
A class allows you to group related functions into methods, making them part of an object.
Example (Calculator.py):
# Calculator.py
class Calculator:
def add(self, a, b):
return a + b
def subtract(self, a, b):
return a - b
def multiply(self, a, b):
return a * b
# Creating an instance (object) of the class
calc = Calculator()
# Testing methods
print(calc.add(5, 3)) # Output: 8
print(calc.subtract(10, 4)) # Output: 6
print(calc.multiply(6, 7)) # Output: 42
Calling Methods the Object-Oriented Way
The object-oriented way of calling methods involves creating an object (instance) of the class
and calling the method using object.method().
Example (main.py - Calling Methods the OOP Way):
from Calculator import Calculator # Importing the class
# Creating an object of the class
calc = Calculator()
# Calling methods using the object
result1 = calc.add(10, 5)
result2 = calc.subtract(20, 7)
print("Addition:", result1) # Output: 15
print("Subtraction:", result2) # Output: 13
4. Semi-Automatic Testing Using assert
Semi-automatic testing helps verify that functions work as expected. Python provides the assert
statement to check conditions.
Example (test_calculator.py):
from Calculator import
Calculator # Creating an object of
Calculator calc = Calculator()
# Test cases
assert calc.add(2, 3) == 5
assert calc.subtract(10, 4) == 6
assert calc.multiply(6, 7) == 42
print("All tests passed successfully!")
If all assertions pass, it prints "All tests passed successfully!", otherwise, it raises an
AssertionError.
5. Using unittest for More Structured Testing
For a more structured testing approach, Python provides the unittest module.
Example (test_calculator_unittest.py):
import unittest
from Calculator import Calculator
class TestCalculator(unittest.TestCase):
def setUp(self):
self.calc = Calculator() # Create a Calculator object for testing
def test_add(self):
self.assertEqual(self.calc.add(2, 3), 5)
def test_subtract(self):
self.assertEqual(self.calc.subtract(10, 4), 6)
def test_multiply(self):
self.assertEqual(self.calc.multiply(6, 7), 42)
if name == " main ":
unittest.main()
Run this file, and Python will execute all test cases, displaying PASS or FAIL messages.
String Methods in Python
Python provides a variety of built-in string methods to manipulate and process strings. Some
commonly used string methods:
Method Description Example
lower() Converts to lowercase "HELLO".lower() → 'hello'
upper() Converts to uppercase "hello".upper() → 'HELLO'
Removes leading and trailing
strip() " hello ".strip() → 'hello'
whitespace
replace(old, new) Replaces a substring "apple".replace("a", "o") → 'opple'
split(delimiter) Splits a string into a list "a,b,c".split(",") → ['a', 'b', 'c']
join(iterable) Joins a list into a string "-".join(['a', 'b', 'c']) → 'a-b-c'
find(substring) Finds the index of a substring "hello".find("e") → 1
Counts occurrences of a
count(substring) "banana".count("a") → 3
substring
Checks if string starts with
startswith(prefix) "hello".startswith("he") → True
prefix
endswith(suffix) Checks if string ends with suffix "hello".endswith("o") → True
Checks if all characters are
isdigit() "123".isdigit() → True
digits
Checks if all characters are
isalpha() "abc".isalpha() → True
letters
Checks if all characters are
isalnum() "abc123".isalnum() → True
letters or digits
Example Code Using String Methods
text = " Python is Fun! "
print(text.lower()) # Output: " python is fun! "
print(text.upper()) # Output: " PYTHON IS FUN! "
print(text.strip()) # Output: "Python is Fun!"
print(text.replace("Fun", "Awesome")) # Output: " Python is Awesome! "
print(text.split()) # Output: ['Python', 'is', 'Fun!']
print("-".join(["Python", "is", "cool"])) # Output: "Python-is-cool"
print(text.find("is")) # Output: 9
print(text.count("n")) # Output: 2
Understanding Underscores in Python
Python uses underscores _ in different ways, and they serve special meanings depending on the
context.
A. Single Leading Underscore (_variable)
Used as a convention to indicate that a variable is intended to be private.
Python does not enforce privacy, but it's a convention to indicate internal use.
class Person:
def init (self, name, age):
self.name = name # Public attribute
self._age = age # Private
(convention)
p = Person("Alice", 25)
print(p.name) # Output: Alice
print(p._age) # Output: 25 (Can be accessed but not recommended)
B. Single Trailing Underscore (variable_)
Used to avoid naming conflicts with Python keywords.
class_ = "BCA" # Avoids conflict with the 'class' keyword
print(class_) # Output: BCA
C. Double Leading Underscore ( variable)
Name Mangling: Python internally renames it to _ClassName variable to prevent
accidental access.
class Example:
def init (self):
self. secret = "hidden"
obj = Example()
# print(obj. secret) # AttributeError: 'Example' object has no attribute ' secret'
print(obj._Example secret) # Output: hidden
D. Double Leading & Trailing Underscores ( init , str )
Used for special (dunder) methods in Python (e.g., init , str , len ).
These methods define how objects behave in built-in operations.
class MyClass:
def init (self, name):
self.name = name
def str (self):
return f"MyClass object with name {self.name}"
obj = MyClass("Alice")
print(obj) # Output: MyClass object with name Alice
E. Single Underscore _ as a Temporary Variable
Used in loops or when a variable's value is not needed.
for _ in range(3):
print("Hello") # Output: Prints "Hello" three times
In Python interactive mode, _ stores the last evaluated expression.
>>> 5 + 3
8
>>> _ * 2 # Uses the last result (8) and multiplies by 2
16
Lists in Python:
A list in Python is an ordered, mutable collection of elements. Lists can store multiple types of data
(integers, strings, floats, objects, etc.).
Creating a List
numbers = [1, 2, 3, 4, 5] # List of integers
fruits = ["apple", "banana", "cherry"] # List of strings
mixed = [10, "hello", 3.14, True] # List with multiple data types
empty_list = [] # An empty list
Storing and Accessing Data in Lists
Accessing Elements by Index
Indexing starts from 0.
Use negative indexing to access elements from the
end. fruits = ["apple", "banana", "cherry", "mango"]
print(fruits[0]) # Output: apple
print(fruits[-1]) # Output: mango
print(fruits[2]) # Output: cherry
Accessing Multiple Elements Using a Loop
for fruit in fruits:
print(fruit)
# Output:
# apple #
banana #
cherry #
mango
Modifying Lists
Changing an Element
fruits[1] = "blueberry"
print(fruits) # Output: ['apple', 'blueberry', 'cherry', 'mango']
Adding Elements
append(item): Adds an item to the end.
insert(index, item): Adds an item at a specific position.
fruits.append("orange") # Adds at the end
print(fruits) # Output: ['apple', 'blueberry', 'cherry', 'mango', 'orange']
fruits.insert(1, "grape") # Adds at index 1
print(fruits) # Output: ['apple', 'grape', 'blueberry', 'cherry', 'mango', 'orange']
Removing Elements
remove(item): Removes the first occurrence of an item.
pop(index): Removes an item at a specific index (default: last item).
del list[index]: Deletes an item.
fruits.remove("cherry") # Removes "cherry"
print(fruits)
last_fruit = fruits.pop() # Removes last item
print(last_fruit, fruits)
del fruits[0] # Removes first item
print(fruits)
Operations on Lists
Concatenation (+)
list1 = [1, 2, 3]
list2 = [4, 5, 6]
combined = list1 + list2
print(combined) # Output: [1, 2, 3, 4, 5, 6]
Repetition (*)
repeated_list = [0] * 5
print(repeated_list) # Output: [0, 0, 0, 0, 0]
Checking Membership (in)
print("apple" in fruits) # Output: True
print("grape" not in fruits) # Output: False
Slicing Lists
Slicing allows extracting a portion of the list.
numbers = [10, 20, 30, 40, 50, 60, 70]
print(numbers[1:4]) # Output: [20, 30, 40] (From index 1 to 3)
print(numbers[:3]) # Output: [10, 20, 30] (First three elements)
print(numbers[3:]) # Output: [40, 50, 60, 70] (From index 3 to end)
print(numbers[-3:]) # Output: [50, 60, 70] (Last three elements)
print(numbers[::2]) # Output: [10, 30, 50, 70] (Every second element)
print(numbers[::-1]) # Output: [70, 60, 50, 40, 30, 20, 10] (Reverse list)
Aliasing (Reference vs Copy)
Aliasing (Both variables refer to the same list)
list1 = [1, 2, 3]
list2 = list1 # Both point to the same memory location
list2.append(4)
print(list1) # Output: [1, 2, 3, 4] (Changes reflect in list1)
Copying a List (Separate Memory)
Use copy() or slicing to create a new copy.
list1 = [1, 2, 3]
list2 = list1[:] # OR list1.copy()
list2.append(4)
print(list1) # Output: [1, 2, 3] (Original list unchanged)
print(list2) # Output: [1, 2, 3, 4]
List Methods
Method Description
append(x) Adds x to the end
insert(i, x) Inserts x at index i
remove(x) Removes first occurrence of x
pop(i) Removes and returns element at index i (last if not specified)
sort() Sorts the list in ascending order
reverse() Reverses the list order
index(x) Returns index of x
count(x) Counts occurrences of x
copy() Returns a copy of the list
Example:
nums = [3, 1, 4, 1, 5, 9, 2]
nums.sort() # Sorts in ascending order
print(nums) # Output: [1, 1, 2, 3, 4, 5, 9]
nums.reverse() # Reverses list
print(nums) # Output: [9, 5, 4, 3, 2, 1, 1]
print(nums.count(1)) # Output: 2 (Counts occurrences of 1)
Working with a List of Lists (2D Lists)
A list can contain other lists, forming a 2D list (Matrix).
matrix =
[ [1, 2, 3],
[4, 5, 6],
[7, 8, 9]
# Accessing elements
print(matrix[0][1]) # Output: 2 (Row 0, Column 1)
print(matrix[2]) # Output: [7, 8, 9] (Third row)
# Iterating over 2D lists
for row in matrix:
for col in row:
print(col, end=" ")
print()
# Output:
#123
#456
#789
*****