INTERNAL ASSIGNMENT - DCA6109_Python_Programming
NAME : Humaira Fathima N
ROLL NO.: 251450622597
PROGRAM: Master of Computer Application (MCA)
ASSIGNMENT SETS: Set 1 & Set 2
SET - I
1a. Explain the difference between implicit and explicit type conversion with suitable
examples.
● Converting data types, also known as type casting, involves changing a variable's data
type. The key distinction between implicit and explicit conversion is who controls the
process: the system does it automatically in implicit conversion, while the
programmer handles it manually in explicit conversion.
● Here’s a breakdown of the differences:
Feature Implicit Type Conversion Explicit Type Conversion
(Type Casting)
Performed By The compiler or The programmer does it
interpreter does it manually.
automatically.
Syntax No special syntax is Requires specific
needed. functions or cast
operators.
Data Loss Generally safe, with no Possible data loss or
data loss (widening). precision issues
(narrowing).
Direction Lower to higher data Higher to lower data types
types (e.g., int to float). (e.g., float to int).
1. Implicit Type Conversion
This process, also called coercion or widening, happens when the system
automatically changes a "smaller" data type to a "larger" one. This is done to
guarantee that operations are compatible.
Example:
a=5 # Integer
b = 2.0 # Float
result = a + b
# Python automatically converts 'a' to a float (5.0) before addition.
print(result) # Output: 7.0
Result: The integer is safely promoted to a float to prevent data loss.
2. Explicit Type Conversion
Commonly referred to as type casting or narrowing, this process necessitates that the
programmer employs built-in functions or operators to enforce a conversion. It is
frequently utilized when there is a potential for data loss, such as eliminating decimal
places from a number.
Example:
num_str = "50"
num_int = int(num_str)
# Explicitly converting a string to an integer to allow math operations.
result = num_int + 10 # Output: 60
Result: This allows the program to treat the string “50” as the numeric value 50.
1b. What risks can arise if a file is not properly closed after completing operations?
● Keeping a file open after finishing operations poses a significant programming risk
since it consumes limited system resources and jeopardizes data integrity.
Primary Risks:
● Data Loss or Corruption: The majority of programming languages utilize buffering,
which involves temporarily saving data in memory before it is recorded on the
physical disk. When a file is closed, a "flush" occurs to guarantee that all data held in
the buffer is properly saved. If the file is left open and the program or computer
unexpectedly crashes, those modifications could be lost or only partially saved,
resulting in corruption.
● Resource Depletion (File Handle Leaks): Operating systems enforce a specific cap
on the number of files that can be opened at the same time by an individual process or
by the entire system. Each open file requires a "file handle" or "descriptor."
Neglecting to close files—particularly within loops—can ultimately result in a "Too
many open files" error, blocking the program from opening additional files or network
sockets.
● Access Conflicts (File Locking): Numerous operating systems, especially Windows,
will lock a file when it is being written to. If your application maintains a file open
longer than necessary, it may prevent other processes—such as backup applications,
antivirus programs, or even different components of your own code—from accessing
or altering the file.
● Performance Decline: Open files consume kernel memory and system resources.
Keeping unclosed files can lead to memory leaks and overall system instability,
especially in extended applications like servers.
2a. What is a list? Explain the insert(), append(), and extend() methods with examples.
● In Python, a list is a fundamental data structure that maintains a sequential, mutable
(modifiable) collection of elements. Lists can contain items of various data types,
including integers, strings, and even additional lists, and they permit duplicate entries.
● Python offers three main methods to add new items to a list: insert(), append(), and
extend().
1. append()
The append() function adds one element to the end of the list.
Argument: Takes exactly one object (of any data type).
Behavior with Iterables: If you append another list, it inserts the whole list as a
single "nested" element.
Example:
nums = [1, 2, 3]
[Link](4) # Result: [1, 2, 3, 4]
[Link]([5, 6]) # Result: [1, 2, 3, 4, [5, 6]]
2. extend()
The extend() method incorporates elements from an iterable (such as a list, tuple, or
string) individually at the end of the existing list.
Argument: It takes a single iterable object as an input.
Behavior: It "unpacks" the iterable and adds each item sequentially.
Example:
nums = [1, 2, 3]
[Link]([4, 5]) # Result: [1, 2, 3, 4, 5]
[Link]("Hi") # Result: [1, 2, 3, 4, 5, 'H', 'i']
3. insert()
The insert() function places an item at a designated index, moving the current
elements to the right.
Arguments: It accepts two arguments: index (the location) and element (the item to
be inserted).
Behaviour: It is more inefficient for large lists since it necessitates shifting all
following items one position to the right.
Example:
fruits = ["apple", "banana"]
[Link](1, "orange") # Result: ["apple", "orange", "banana"]
Method Position Number of Items Complexity
append() Always at the end. Adds 1 single O(1)
element.
extend() Always at the end. Adds multiple O(k) (k = items
items from an added)
iterable.
insert() At specified index. Adds 1 single O(n) (n = list
element. length)
2b. Explain the use of following string functions: - upper(), lower(), isdigit(), isalpha(), split(),
join() with example.
● In Python, there are built-in methods known as string functions that are utilized for
manipulating or querying text data. As of 2026, these functions continue to be
essential for standard text processing.
1. upper()
Transforms all lowercase letters in a string to uppercase.
Functionality: Non-alphabetic characters (such as numbers and symbols) stay the
same.
Example:
text = "hello 123"
print([Link]()) # Output: "HELLO 123"
2. lower()
Changes all uppercase letters in a string to their lowercase equivalents.
Application: Frequently utilized for comparisons that ignore case sensitivity.
Example:
text = "PYTHON"
print([Link]()) # Output: "python"
3. isdigit()
Returns True if every character in the string is a digit (0-9) and the string is not empty;
otherwise, it returns False.
Note: It does not consider decimal points or negative signs as digits.
Example:
print("12345".isdigit()) # Output: True
print("12.34".isdigit()) # Output: False
4. isalpha()
Returns True if every character in the string is a letter (A-Z or a-z).
Note: It will return False if there are spaces, digits, or special characters.
Example:
print("Hello".isalpha()) # Output: True
print("Hello 123".isalpha()) # Output: False (contains space and numbers)
5. split()
Divides a string into a list of substrings using a designated separator (whitespace is
the default).
Example:
text = "apple,banana,cherry"
print([Link](",")) # Output: ['apple', 'banana', 'cherry']
6. join()
Joins items from an iterable (such as a list) into one string, using a designated string to
separate the elements.
Example:
words = ["Python", "is", "fun"]
print(" ".join(words)) # Output: "Python is fun"
3a. Why is exception handling important? How can multiple exceptions be handled in
Python? Explain with an example.
● Exception handling is essential in programming as it provides a “safety net” to control
unforeseen runtime errors without leading to a sudden program crash. As of 2026, it
continues to be an established best practice for crafting robust software that can either
recover from failures or shut down gracefully while delivering useful feedback to
users.
Reasons Why Exception Handling is Crucial
● Avoids Sudden Termination: It enables a program to keep running or to terminate
safely even when an error (such as a missing file or a network timeout) arises.
● Enhanced User Experience: Instead of displaying confusing system tracebacks,
developers can offer clear and constructive error messages.
● Separation of Responsibilities: It differentiates the core business logic from
error-handling code, resulting in a neater and more manageable program.
● Resource Management: It guarantees that essential resources, like file handles or
database connections, are appropriately released even in the event of an error.
● Increased Security: Proper handling prevents the unintended exposure of sensitive
system details that unhandled tracebacks might disclose.
Handling Multiple Exceptions in Python
Python allows you to handle multiple types of exceptions using two primary approaches:
1. Individual except Blocks
You can provide separate except clauses for different error types. This is used when each error
requires a unique response.
Example:
try:
num = int(input("Enter a number: "))
result = 10 / num
except ValueError:
print("Error: Please enter a valid numeric digit.")
except ZeroDivisionError:
print("Error: You cannot divide by zero.")
2. Grouped Exceptions (Tuple)
If you wish to manage various exceptions in a similar manner, you can combine them into a
tuple in one except clause.
Example:
try:
# Code that might raise different errors
value = int("abc")
except (ValueError, TypeError, ZeroDivisionError) as e:
print(f"A common error occurred: {e}")
3. Exception Groups (Python 3.11)
In Python 3.11, for more complex situations that require managing concurrent tasks (such as
asyncio), the new except* syntax was introduced to address ExceptionGroup objects, which
can encompass several errors happening at the same time.
Example: Handling Multiple Exceptions
This example shows a comprehensive framework featuring distinct handlers, a combined
handler, and a cleanup section:
try:
data = [10, 20, 30]
index = int(input("Enter index to divide 100 by: "))
result = 100 / data[index]
print(f"Result: {result}")
except IndexError:
print("Error: That index does not exist in the list.")
except (ValueError, TypeError):
# Handles both non-numeric input and type mismatches
print("Error: Invalid input type or value.")
except ZeroDivisionError:
print("Error: The value at that index is zero.")
except Exception as e:
# Catch-all for any other unexpected errors
print(f"An unexpected error occurred: {e}")
finally:
# This block always executes regardless of what happened above
print("Processing complete.")
3b. Discuss the different methods used to read data from a file.
● In 2026, reading data from files continues to be a fundamental programming task,
with techniques classified according to how the operating system accesses the
physical information and how high-level languages like Python offer abstractions for
programmers.
I. Methods of Operating System Access
These techniques explain how the underlying system retrieves data from storage.
● Sequential Access: This is the most straightforward method, where data is read in a
linear fashion, one record at a time, starting from the beginning. It is very efficient for
processing large datasets in sequence but can be slow when searching for specific
records.
● Direct (Random) Access: This method enables immediate access to any block or
record by its address without the need to scan through preceding data. It is crucial for
database systems that require quick retrieval of specific filtered data.
● Indexed Sequential Access: This is a combined method where an index table
contains pointers to various file blocks. It allows the system to look up the index first
and then directly access the needed record.
● Content-Addressable Access (CAA): This approach retrieves data based on its
content (utilizing a unique hash) rather than its position. It is commonly employed in
caching and data deduplication.
II. Programming Methods
Contemporary Python includes numerous built-in functions to efficiently manage file data.
● read(): This function retrieves the complete content of a file as a single string.
Although it's straightforward, using it on very large files can risk depleting system
RAM.
● readline(): This function reads a single line at a time from the current file pointer
position. It is particularly useful for handling files that cannot fit into memory all at
once.
● readlines(): This method reads all lines from the file and saves them in a list of
strings. It is beneficial for accessing specific lines by their index (e.g., lines[2]).
● Line-by-Line Iteration: A highly memory-efficient method for processing a file is to
iterate directly through the file object (e.g., for line in file:). This approach reads the
file in a "lazy" manner, loading just one line into memory at any given moment.
● pathlib Module: This is the modern, object-oriented method for file management.
Functions like Path.read_text() or Path.read_bytes() offer a cross-platform approach to
reading entire files without the need for manual string-based paths.
4a. What are view functions in Flask? Explain static and dynamic routes in detail.
● In Flask, the fundamental components for managing web requests and providing
content to users are view functions and routing.
View Functions
A view function is a Python function that processes an incoming HTTP request and produces
a response.
● Bridge Role: It serves as the link between a particular URL and the logic that creates
a webpage's content.
● Mapping: You associate a view function with a URL by using the @[Link]()
decorator.
● Response: The function can yield different kinds of data, such as plain text, HTML
strings, rendered templates (using render_template), or JSON data (utilizing jsonify).
Static Routes
Static routes are predetermined URL paths that remain constant and consistently direct to the
same view function.
● Attributes: These URLs lack any variable components and are perfect for unchanging
pages such as "Home," "About Us," or "Contact."
● Example:
@[Link]('/about')
def about():
return "This is the About Page"
Visiting [Link] will always trigger this specific function.
Dynamic Routes
Dynamic routes feature variable sections that enable a single route to accommodate multiple
related URLs by capturing segments of the path and forwarding them as arguments to the
view function.
Variable Rules: You define dynamic portions using angled brackets: <variable_name>.
Converters: You can limit the type of data a variable can take by using a converter
(<converter:variable_name>).
● string (default): Accepts any text that does not include a slash.
● int: Accepts only positive whole numbers.
● float: Accepts positive decimal values.
● path: Similar to a string but can also include slashes.
● uuid: Accepts specific UUID format strings.
Example of a Dynamic Route:
@[Link]('/user/<username>')
def profile(username):
return f"Welcome to the profile of {username}!"
@[Link]('/post/<int:post_id>')
def show_post(post_id):
return f"Displaying Post ID: {post_id}"
In the initial example, accessing /user/john or /user/mary will transmit "john" or "mary" to the
username variable, enabling the page to tailor its response accordingly.
4b. Write a regular expression for validating Indian mobile numbers entered by users.
(+91-XXXXXXXXXX)
● To check if an Indian mobile number is in the exact format +91-XXXXXXXXXX,
you can use the following regex:
● ^\+91-[6-9]\d{9}$
Explanation of the Pattern:
^: Ensures that the string starts here, confirming no characters appear before the mobile
number.
\+91-: Matches the characters "+91" followed by a required hyphen. The \ is used to escape
the + symbol since it is a special character in regex.
[6-9]: Represents the first digit of the 10-digit mobile number. In India, mobile numbers must
begin with either 6, 7, 8, or 9.
\d{9}: Matches precisely nine additional digits (0-9) to make up the complete 10-digit mobile
number.
$: Ensures that the string ends here, confirming no extra characters or spaces appear after the
mobile number.
Example:
import re
def validate_indian_mobile(number):
pattern = r"^\+91-[6-9]\d{9}$"
if [Link](pattern, number):
return "Valid Number"
else:
return "Invalid Number"
# Test cases
print(validate_indian_mobile("+91-9876543210")) # Valid
print(validate_indian_mobile("+91-5876543210")) # Invalid (starts with 5)
print(validate_indian_mobile("9876543210")) # Invalid (missing +91-)
5a. Explain the role of game loops and event handling in game development.
In Python, these principles are frequently employed using libraries such as Pygame-CE
(Community Edition) or Arcade.
1. The Python Game Loop
The game loop is usually a while loop that maintains the program's execution and
synchronization. It stops the game from closing immediately and oversees the timing of each
"frame" or "tick."
● Structure: A typical loop adheres to a three-step process: Handle Events
\(\rightarrow\) Update State \(\rightarrow\) Render Display.
● Framerate Control: The speed of Python's execution may differ based on the
hardware used. To avoid the game running too quickly, developers utilize a clock
object, like [Link]().tick(60), to limit the loop to a steady
frames-per-second (FPS) rate.
● State Management: This aspect involves calculating physics and logic (for instance,
gravity, AI movement) in each cycle.
2. Handling Events in Python
Events in Python are distinct signals (such as a key press or a mouse click) that are kept in an
Event Queue, which operates as a "First-In-First-Out" (FIFO) list overseen by the
operating system.
The Event Queue: Every user action is appended to the end of the queue. The game loop
needs to "drain" this queue at the beginning of each frame to stay responsive.
Non-Blocking Polling: In Python, functionalities like [Link]() gather these events
without halting the entire game. If the queue is empty, the loop simply moves on to the update
phase.
Specific Event Types: Handlers generally look for:
● QUIT: Activated when the user closes the window.
● KEYDOWN / KEYUP: Utilized to identify individual key presses (for instance,
K_ESCAPE to exit or K_SPACE to jump).
● MOUSEMOTION: Monitors cursor positions for targeting or hovering over the user
interface.
5b. What are transactions? Explain importance of SAVEPOINT in transaction failure.
In Python, both transactions and savepoints are handled according to the Python Database
API Specification (DB-API 2.0) or through higher-level Object-Relational Mappers (ORMs)
such as SQLAlchemy and Django.
1. Transactions in Python
● When executing a command via a connection (for instance, sqlite3, psycopg2), a
transaction begins automatically if autocommit is turned off.
● To finalize all pending changes, use [Link]().
● In the event of a failure, employ [Link]() within an except block to
reverse the entire transaction, thereby upholding ACID principles such as atomicity.
2. Savepoints and Partial Failures
A SAVEPOINT enables you to establish "checkpoints" within a transaction. If a certain
operation encounters an error, you can revert to that checkpoint without affecting earlier
successful actions within the same transaction.
Significance in Error Management
● Error Containment: You can enclose "high-risk" operations within a savepoint. If
they fail, you only reverse the problematic part while keeping the preceding data
intact.
● Complicated Processes: This is beneficial for loops where you want to attempt a
failed operation again or bypass a single flawed record rather than restarting the entire
multi-step procedure.
● Nested Transactions: In Python ORMs, savepoints are the main method for
facilitating "nested" transactions (for example, if an inner transaction fails, it shouldn't
necessarily cause the outer transaction to fail as well).
6a. Explain the significance of PEP8 guidelines in Python development.
In Python development, PEP 8 (Python Enhancement Proposal 8) serves as the definitive
style guide that standardizes code formatting and structure. Its importance stems from its
fundamental principle: "Readability counts."
1. Major Foundations of Importance
Clarity and Upkeep: Code is reviewed far more frequently than it is created. Following a
consistent style helps developers (and their future selves) to grasp the logic quickly without
grappling with inconsistent formatting.
Effortless Teamwork: By 2026, where large-scale and open-source projects become
commonplace, PEP 8 offers a shared framework. It resolves "style conflicts" during code
reviews, enabling teams to concentrate on logic instead of debating spacing issues.
Professional Expectations: Following PEP 8 is frequently a requirement for professional
roles and contributions to significant open-source projects. It reflects a developer's diligence
and level of expertise.
Bug Prevention: Certain guidelines are specifically designed to avert errors, such as
prohibiting the combination of tabs and spaces, which leads to IndentationError in Python 3.
2. Core Guidelines Summary
Category PEP 8 Recommendations
Indentation Use 4 spaces per level; never use tabs.
Naming Use snake_case for variables and functions, PascalCase for class
names, and UPPER_CASE for constants.
Line Length Restrict each line to no more than 79 characters.
Whitespace Utilize single spaces around operators (for instance, x = y + 1) while
refraining from using spaces within parentheses.
Imports Position at the beginning of the file, categorized into Standard Library,
Third-Party, and Local.
6b. What do you understand about Continuous Integration and Continuous Deployment
(CI/CD) in the context of Python applications?
In 2026, Continuous Integration (CI) and Continuous Deployment (CD) serve as the core
principles of contemporary Python development, transforming the process of software
delivery from high-pressure "events" into a regular, automated "non-event."
1. Continuous Integration (CI)
CI involves the routine merging of code changes into a shared repository—typically multiple
times throughout the day—where they are automatically built and tested.
Regarding Python specifically: As Python is an interpreted language, the "build" phase
concentrates less on compilation and more on setting up the environment (using tools like pip
or poetry) and packaging.
Automated Validation: Each code push initiates a pipeline that executes linters (such as
flake8 or Ruff) to ensure style adherence and unit tests (using pytest or unittest) to confirm
correctness.
Primary Goal: To identify bugs and integration conflicts at an early stage, avoiding
"integration hell" and guaranteeing the main branch remains stable.
2. Continuous Deployment (CD)
CD enhances the pipeline by automatically releasing each code modification that successfully
completes the CI stage into production without any human involvement.
The Distinction Between "Delivery" and "Deployment":
Continuous Delivery: The code is always prepared for deployment, but a human must
initiate the push to production.
Continuous Deployment: The whole process is automated; if the tests are successful, the
code goes live within minutes.
Infrastructure as Code (IaC): By 2026, Python applications are commonly deployed using
IaC tools like Ansible (which is written in Python) or Terraform to guarantee that
environments are consistent and reproducible.