Core Python / Lists#
What is a list in Python, and how does it differ from arrays in other programming languages?
Lists are ordered sequences of elements, which can be of different types including other lists. In other programming languages, arrays are of a specific type and generally not dynamically expandable.
What is list slicing, and how is it performed in Python?
List slicing in Python is a way to create a new list by extracting a subset of elements from an existing list. Slicing is performed using a colon
:
and optional start, stop, and step indices within square brackets[]
.How do list access operations compare to those from strings?
Virtually identical. The key difference is that strings are immutable and only contain characters.
What happens when you pass a list to the
append()
method? To theextend()
method?The entire list becomes the last element of the original list. With
extend()
, each element of the second list is appended to the original list.>>> x = ["Duke", "University"] >>> y = ["Financial", "Technology"] >>> x.append(y) >>> x ['Duke', 'University', ['Financial', 'Technology']] >>> x.extend(y) >>> x ['Duke', 'University', ['Financial', 'Technology'], 'Financial', 'Technology']
How do you insert an item at a specific index in a list?
Use the
insert(pos, element)
function on lists. Continuing the previous example ->>> x.insert(1,"Blue Devils") >>> x ['Duke', 'Blue Devils', 'University', ['Financial', 'Technology'], 'Financial', 'Technology']
Discuss the difference between the
pop()
andremove()
methods in Python lists.Both the
pop()
andremove()
methods are used to remove elements from a list, but they differ in their functionality:pop()
:The
pop()
method removes and returns the last element from the list by default.It takes an optional index argument, allowing you to remove and return the element at the specified index.
If no index is specified,
pop()
removes and returns the last element from the list.After calling
pop()
, the list is modified in place, and the removed element is returned.If the list is empty, calling
pop()
raises anIndexError
. (covered later )
remove()
:The
remove()
method removes the first occurrence of a specified value (its argument) from the list.The list is modified in place.
If the specified value is not found in the list, calling remove() raises a
ValueError
. (errors are covered later in the notebooks
# Example of using pop() my_list = [1, 2, 3, 4, 5] removed_element = my_list.pop() print("Removed element:", removed_element) # Output: Removed element: 5 print("List after pop:", my_list) # Output: List after pop: [1, 2, 3, 4] # Example of using pop() with index element_at_index_two = my_list.pop(2) print("Element at index two:", element_at_index_two) # Output: Element at index two: 3 print("List after pop(2):", my_list) # Output: List after pop(2): [1, 2, 4] # Example of using remove() my_list.remove(2) print("List after remove(2):", my_list) # Output: List after remove(2): [1, 4]
How do you sort a list in Python, and what is the default sorting order?
Python provides two ways to sort lists:
Using the
sort()
method: This method sorts the original list in place, meaning it modifies the order of the elements within the same list.Using the
sorted()
function: This function creates a new sorted list based on the original list. The original list remains unchanged.
Both sort() and sorted() methods sort elements by their natural ordering by default. This means:
Numbers are sorted numerically (from lowest to highest).
Strings are sorted alphabetically (case-sensitive, a comes before A).
# sort() numbers = [5, 2, 8, 1] numbers.sort() # Sorts the list in-place print(numbers) # Output: [1, 2, 5, 8] #sorted() fruits = ["banana", "apple", "cherry"] sorted_fruits = sorted(fruits) # Creates a new sorted list print(sorted_fruits) # Output: ["apple", "banana", "cherry"] print(fruits) # Original list remains unchanged
Note that
sort()
is behavior(functionality) tied to the list object whilesorted()
is a built-in function.Customizing Sort Order:
Both
sort()
andsorted()
offer ways to customize the sorting order. You can provide a key function that defines how elements should be compared for sorting:# Sort fruits by length (shortest to longest) def by_length(fruit): return len(fruit) fruits = ["banana", "apple", "cherry"] sorted_fruits = sorted(fruits, key=by_length) print(sorted_fruits) # Output: ["apple", "cherry", "banana"]
Compare the sort() method with the sorted() function in Python lists.
See previous answer
Explain deep vs shallow copying including possible tradeoffs.
A shallow copy creates a new object (list) that contains references to the same elements as the original list. If the elements are mutable objects (e.g., lists, dictionaries, or custom objects), the new list and the original list will share references to those mutable objects.
A deep copy creates a new object (list) and recursively copies all nested objects (e.g., nested lists, dictionaries, or custom objects) into new objects as well. This way, the new list and the original list are entirely independent, and modifying one does not affect the other.
Tradeoffs:
Memory Usage: Deep copying can be more memory-intensive than shallow copying, especially for large and deeply nested data structures, as it creates copies of all nested objects.
Performance: Deep copying is generally slower than shallow copying due to the recursive copying of nested objects.
Mutability: If you only need to modify the outermost list and not the nested objects, a shallow copy may be sufficient and more efficient.
Data Integrity: Deep copying provides better data integrity by ensuring that modifications to the copy do not affect the original data. This can be important in certain scenarios, such as multithreading or when passing data between functions.
What are the performance implications of removing an element from the middle of a list versus the end?
Removing an element from the end of a list is a constant-time operation, denoted as O(1). This means that the time it takes to remove the last element is independent of the size of the list.
Removing an element from the middle of a list is a linear-time operation, denoted as O(n), where n is the length of the list. This means that the time it takes to remove an element from the middle grows linearly with the size of the list.
To remove an element from the middle of a list, Python has to shift all the elements after the removed element one position to the left to maintain the order and fill the gap. This process involves moving all the subsequent elements, which takes longer as the list grows larger.
The performance difference between removing an element from the end versus the middle of a list can be significant, especially for large lists.