Unit 3: String, Lists, Tuples and Dictionaries - Subjective Questions
INT108 — Python Programming • Practice Questions with Detailed Answers
20 questions
Explain why a Python string is called a compound data type. Describe how individual characters are accessed, including the use of positive and negative indices.
A string is called a compound data type because it consists of a sequence of smaller values called characters.
- Each character can be accessed using the indexing operator
[]. - Positive indexing begins at
0and moves from left to right. - Negative indexing begins at
-1and moves from right to left.
For example, for word = "Python":
word[0]returns"P".word[3]returns"h".word[-1]returns"n".word[-2]returns"o".
An index outside the valid range raises an IndexError. Although individual characters can be accessed, they cannot be modified directly because strings are immutable.
Describe how the length of a string is determined in Python. Write a program that traverses a string and displays each character with its index.
The built-in len() function returns the number of characters in a string, including spaces and punctuation.
For example, len("Python") returns 6. The valid positive indices therefore range from 0 to len(string) - 1.
A string can be traversed using a for loop:
text = "Python"
for index in range(len(text)):
print(index, text[index])
The output is:
0 P
1 y
2 t
3 h
4 o
5 n
A direct traversal is also possible using for character in text, but the index-based form is useful when both positions and characters are required.
Explain string slicing in Python. What do the expressions text[start:stop:step], text[:], text[::-1], and text[2:7:2] represent?
String slicing extracts a portion of a string without modifying the original string. Its general syntax is text[start:stop:step].
startis the index at which the slice begins.stopis excluded from the result.stepspecifies the distance between selected characters.- Omitted values are replaced by suitable defaults.
The expressions mean:
text[:]: creates a slice containing the entire string.text[::-1]: selects the entire string with a step of-1, producing the reversed string.text[2:7:2]: selects characters at indices2,4, and6, provided those indices exist.
For text = "Programming", text[2:7:2] returns "orm". Slices do not normally raise an error when their boundaries extend beyond the valid index range; Python adjusts the boundaries automatically.
How are strings compared in Python? Explain lexicographical comparison, case sensitivity, and the role of Unicode values with suitable examples.
Python compares strings lexicographically, character by character from left to right.
- Corresponding characters are compared until a differing pair is found.
- The comparison is based on Unicode code-point values.
- If one string is a complete prefix of another, the shorter string is considered smaller.
- String comparison is case-sensitive.
Examples:
"apple" == "apple"isTrue."apple" < "banana"isTruebecause"a"precedes"b"."cat" < "cater"isTruebecause"cat"is a prefix of the longer string."Apple" == "apple"isFalse."Z" < "a"isTruebecause the Unicode value of uppercaseZis less than that of lowercasea.
For case-insensitive comparison, both strings may be normalized using casefold() or lower(), such as first.casefold() == second.casefold().
Explain the purpose and syntax of the string find() method. How can its return value be used safely in a program?
The find() method searches for the first occurrence of a substring within a string.
Its common forms are:
text.find(substring)text.find(substring, start)text.find(substring, start, stop)
It returns the index of the first matching occurrence. If no match exists, it returns -1 instead of raising an exception.
Example:
text = "banana"
position = text.find("ana")
if position != -1:
print("Found at index", position)
else:
print("Not found")
Here, the result is 1. In text.find("na", 3), searching starts at index 3, so the result is 4. A program should test the result against -1 before using it as a valid position.
Develop and explain a Python program that uses looping and counting to determine the frequencies of all characters in a string, ignoring letter case.
A dictionary can store each character as a key and its frequency as the corresponding value.
text = input("Enter text: ").casefold()
frequencies = {}
for character in text:
if character in frequencies:
frequencies[character] += 1
else:
frequencies[character] = 1
for character, count in frequencies.items():
print(repr(character), count)
Explanation:
casefold()converts case variants into a form suitable for case-insensitive counting.- The loop visits each character once.
- Membership testing checks whether the character is already a dictionary key.
- An existing count is incremented; otherwise, a new count of
1is created.
If the string has length , the average time complexity is because dictionary lookup and update are normally . The dictionary requires up to space, where is the number of distinct characters.
Define a Python list. Explain list values, list length, element access, and membership testing with examples.
A list is an ordered, mutable sequence of values. It is written using square brackets, and its elements may have the same or different data types.
Example:
values = [10, "Python", 3.5, True]
len(values)returns4, which is the list length.values[0]returns10using positive indexing.values[-1]returnsTrueusing negative indexing."Python" in valuesreturnsTrue.7 not in valuesreturnsTrue.
Accessing an index outside the range from -len(values) to len(values) - 1 raises an IndexError. Membership operators test complete list elements; they do not automatically search inside nested strings or nested lists.
Describe the major list operations in Python, including concatenation, repetition, appending, insertion, extension, and element replacement.
Important list operations include:
- Concatenation:
[1, 2] + [3, 4]creates[1, 2, 3, 4]. - Repetition:
[0] * 3creates[0, 0, 0]. - Appending:
items.append(value)adds one value at the end. - Insertion:
items.insert(index, value)inserts a value at a specified position. - Extension:
items.extend(other)adds every element from another iterable. - Replacement:
items[index] = valuechanges an existing element.
Example:
items = [1, 2]
items.append(3) # [1, 2, 3]
items.insert(1, 10) # [1, 10, 2, 3]
items.extend([4, 5]) # [1, 10, 2, 3, 4, 5]
items[0] = 100 # [100, 10, 2, 3, 4, 5]
The + operator creates a new list, whereas methods such as append(), insert(), and extend() modify the existing list.
Explain list slicing and slice assignment. How do these operations differ from string slicing?
List slicing uses the syntax items[start:stop:step] and returns a new list containing selected elements.
Example:
items = [0, 1, 2, 3, 4, 5]
part = items[1:5:2] # [1, 3]
copy = items[:] # shallow copy
Because lists are mutable, a slice can also appear on the left side of an assignment:
items[1:3] = [10, 20, 30]
This replaces the elements at indices 1 and 2 and may change the list length. A slice can be removed with items[1:3] = [].
Both string and list slicing create new sequence objects. However, strings are immutable, so string slices cannot be assigned to. Lists support slice assignment because their contents can be changed.
Compare the different ways of deleting elements from a list using del, pop(), remove(), and slice assignment.
Python provides several list-deletion techniques:
del items[index]deletes an element by position and returns no value.del items[start:stop]deletes a range of elements.items.pop()removes and returns the last element.items.pop(index)removes and returns the element at a specified index.items.remove(value)removes the first occurrence of a specified value.items[start:stop] = []deletes a slice through slice assignment.
Example:
items = [10, 20, 30, 20]
del items[0] # [20, 30, 20]
removed = items.pop() # removed is 20; list is [20, 30]
items.remove(20) # [30]
pop() raises IndexError for an invalid index or an empty list. remove() raises ValueError if the requested value is absent.
Explain how for loops are used with lists. Write a program to calculate the sum, average, minimum, and maximum of a non-empty numeric list without using sum(), min(), or max().
A for loop visits each list element in sequence. Accumulators can be used to compute aggregate results.
numbers = [12, 5, 18, 9, 6]
total = 0
smallest = numbers[0]
largest = numbers[0]
for number in numbers:
total += number
if number < smallest:
smallest = number
if number > largest:
largest = number
average = total / len(numbers)
print("Sum:", total)
print("Average:", average)
print("Minimum:", smallest)
print("Maximum:", largest)
Explanation:
totalaccumulates all elements.smallestandlargestare initialized using the first element.- Each value is compared with the current minimum and maximum.
- The average is calculated as .
The algorithm takes time and additional space. The list must be checked separately if it may be empty.
Explain how lists behave when passed as parameters to functions. Distinguish between modifying a list and rebinding a parameter to a new list.
When a list is passed to a function, the parameter refers to the same list object as the argument. Therefore, mutations performed through the parameter are visible to the caller.
def add_item(values):
values.append(100)
data = [1, 2]
add_item(data)
# data is now [1, 2, 100]
Rebinding the parameter does not replace the caller's variable:
def replace_list(values):
values = [10, 20]
data = [1, 2]
replace_list(data)
# data is still [1, 2]
In the first function, append() mutates the shared object. In the second, assignment makes the local parameter refer to a different object. A function can avoid changing the original by working on a shallow copy such as values.copy().
What is a nested list? Explain how elements are accessed and traversed in a two-dimensional list representing a matrix.
A nested list is a list containing one or more lists as elements. It can represent tabular data or a matrix.
Example:
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
matrix[1]returns the second row,[4, 5, 6].matrix[1][2]returns6.- The first index selects a row and the second selects a column.
The matrix can be traversed using nested loops:
for row in matrix:
for value in row:
print(value, end=" ")
print()
For index-based traversal:
for row in range(len(matrix)):
for column in range(len(matrix[row])):
print(matrix[row][column])
Using len(matrix[row]) allows rows to have different lengths.
Distinguish between lists and tuples with special reference to mutability, syntax, operations, and appropriate use cases.
Lists and tuples are both ordered sequence types, but they differ mainly in mutability.
Lists:
- Written using square brackets, such as
[1, 2, 3]. - Mutable: elements can be replaced, inserted, or deleted.
- Suitable for collections that are expected to change.
- Provide mutating methods such as
append(),extend(), andremove().
Tuples:
- Usually written using parentheses, such as
(1, 2, 3). - Immutable: their element references cannot be replaced or deleted.
- Suitable for fixed records and values that should remain stable.
- Can be dictionary keys when all their elements are hashable.
Both support indexing, slicing, membership testing, iteration, concatenation, repetition, len(), count(), and index(). A one-element tuple requires a trailing comma, as in (5,); (5) is simply the integer 5.
Explain tuple packing, tuple unpacking, and simultaneous tuple assignment. Show how tuple assignment can swap two values without a temporary variable.
Tuple packing combines multiple values into one tuple:
record = "Asha", 20, "Python"
This is equivalent to record = ("Asha", 20, "Python").
Tuple unpacking assigns the tuple's elements to separate variables:
name, age, subject = record
The number of target variables must normally match the number of values. Extended unpacking can collect extra values:
first, *middle, last = [1, 2, 3, 4]
Tuple assignment can swap values directly:
a = 10
b = 20
a, b = b, a
Python first evaluates and packs the right-hand values as (20, 10) and then unpacks them into a and b. Thus, a becomes 20 and b becomes 10 without an explicit temporary variable.
How can tuples be used as return values from functions? Write and explain a function that returns both the quotient and remainder of integer division.
A Python function can return multiple values separated by commas. These values are packed into a tuple and can be unpacked by the caller.
def quotient_remainder(dividend, divisor):
quotient = dividend // divisor
remainder = dividend % divisor
return quotient, remainder
q, r = quotient_remainder(17, 5)
print(q) # 3
print(r) # 2
The returned value is the tuple (3, 2). The result follows the division identity:
In general:
Returning tuples is useful when several related results must be produced by one function. The divisor should be checked if it may be zero because division by zero raises ZeroDivisionError.
Describe the fundamental dictionary operations in Python, including creation, access, insertion, update, membership testing, and deletion.
A dictionary stores key-value pairs. Its keys must be unique and hashable.
student = {"name": "Ravi", "marks": 82}
Fundamental operations include:
- Access:
student["name"]returns"Ravi". - Safe access:
student.get("grade", "Not assigned")supplies a default when the key is absent. - Insertion:
student["course"] = "Python"creates a new pair. - Update:
student["marks"] = 90changes an existing value. - Membership:
"marks" in studenttests keys and returnsTrue. - Deletion:
del student["course"]removes a pair. - Remove and return:
student.pop("marks")removes the key and returns its value.
Using dictionary[key] with a missing key raises KeyError. Dictionary values may be mutable, but keys must be hashable types such as strings, numbers, or suitable tuples.
Explain the purpose of the dictionary methods keys(), values(), items(), get(), update(), setdefault(), pop(), and clear().
The major dictionary methods perform the following tasks:
keys()returns a dynamic view of all keys.values()returns a dynamic view of all values.items()returns a dynamic view of(key, value)pairs.get(key, default)returns a value without raisingKeyErrorwhen the key is absent.update(other)inserts new pairs and replaces values for matching keys.setdefault(key, default)returns the existing value or inserts the key with the default value.pop(key)removes a key and returns its value.clear()removes all entries.
Example traversal:
scores = {"Asha": 90, "Ravi": 84}
for name, score in scores.items():
print(name, score)
Dictionary view objects reflect later changes to the dictionary. A dictionary should not normally have its size changed while it is being directly iterated.
Explain how a dictionary can be used to represent a sparse matrix. Compare this representation with a conventional nested-list matrix.
A sparse matrix contains mostly zero values. Storing every zero in nested lists wastes memory, so a dictionary can store only the nonzero entries.
For example, the matrix
can be represented as:
matrix = {
(0, 2): 5,
(1, 1): 8,
(2, 0): 2
}
Each key is a (row, column) tuple, and each value is the nonzero matrix element. An element can be read using:
value = matrix.get((row, column), 0)
If a position is absent, get() returns 0.
A dense nested-list matrix requires stored elements. If only entries are nonzero, the dictionary representation requires approximately entries. It is advantageous when , although it has dictionary overhead and is less efficient when most entries are nonzero.
Explain aliasing and copying in Python lists. Distinguish assignment, shallow copying, and deep copying, especially for nested lists.
Aliasing occurs when multiple variables refer to the same object:
first = [1, 2, 3]
second = first
second.append(4)
Both variables now observe [1, 2, 3, 4], and first is second is True.
A shallow copy creates a new outer list:
second = first.copy()
# Equivalent alternatives: first[:] or list(first)
Now first is second is False. However, nested mutable objects are still shared:
first = [[1, 2], [3, 4]]
second = first.copy()
second[0].append(9)
The first inner list changes through both outer lists because it is aliased.
A deep copy recursively copies nested objects:
import copy
second = copy.deepcopy(first)
Changes to nested lists in second no longer affect first. Shallow copying is sufficient for flat lists or when nested sharing is intended; deep copying is appropriate when an independent nested structure is required, though it uses more time and memory.
Explain why a Python string is called a compound data type. Describe how individual characters are accessed, including the use of positive and negative indices.
A string is called a compound data type because it consists of a sequence of smaller values called characters.
- Each character can be accessed using the indexing operator
[]. - Positive indexing begins at
0and moves from left to right. - Negative indexing begins at
-1and moves from right to left.
For example, for word = "Python":
word[0]returns"P".word[3]returns"h".word[-1]returns"n".word[-2]returns"o".
An index outside the valid range raises an IndexError. Although individual characters can be accessed, they cannot be modified directly because strings are immutable.
Did this save you a night before the exam?
LPU Notes is free, and it stays free. Ads cover part of the server bill. The rest comes out of a student's own pocket: the domain, the storage, and keeping the site up through the weeks everyone needs it at once.
The payment button didn't load. An ad blocker or a filtered network is the usual reason. to try again.
Nothing here is ever locked, and nothing unlocks. Chip in only if it was worth it. What it pays for →